@vibecontrols/agent 2026.602.1 → 2026.602.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/dist/{agent-config-85pskv43.js → agent-config-4ppenhqp.js} +1 -1
  2. package/dist/{agent-ready-tracker-zp6p8e6f.js → agent-ready-tracker-kgs7td6t.js} +1 -1
  3. package/dist/app-9j2t5geq.js +2 -0
  4. package/dist/bootstrap-workspace-qgs6d5f0.js +2 -0
  5. package/dist/bootstrap.service-vg72w8pa.js +2 -0
  6. package/dist/{bridge-client-341r9rry.js → bridge-client-1fxza4p7.js} +1 -1
  7. package/dist/cli.js +1 -1
  8. package/dist/daemon-profile-gwdcqx0q.js +2 -0
  9. package/dist/esm-6f3dfn6v.js +2 -0
  10. package/dist/{finalize-retry-handle-registry-vv241fsq.js → finalize-retry-handle-registry-xnm9kxry.js} +1 -1
  11. package/dist/{finalize-retry-worker-xp1nhv3c.js → finalize-retry-worker-dvykrzed.js} +1 -1
  12. package/dist/gateway-client-9kwnmk89.js +2 -0
  13. package/dist/{getMachineId-bsd-a56s0v8c.js → getMachineId-bsd-753751sw.js} +1 -1
  14. package/dist/{getMachineId-darwin-w9k0yw9r.js → getMachineId-darwin-na1pranq.js} +1 -1
  15. package/dist/{getMachineId-linux-anh31jbf.js → getMachineId-linux-dmn0ncdm.js} +1 -1
  16. package/dist/{getMachineId-unsupported-5hv3pwca.js → getMachineId-unsupported-yv77j894.js} +1 -1
  17. package/dist/{getMachineId-win-njb8tery.js → getMachineId-win-9hmyqmm0.js} +1 -1
  18. package/dist/highlights-00fcgwwq.js +2 -0
  19. package/dist/highlights-23bc8zge.js +2 -0
  20. package/dist/highlights-4mhb2pb0.js +2 -0
  21. package/dist/highlights-q7w64nwb.js +2 -0
  22. package/dist/highlights-xwdw5xay.js +2 -0
  23. package/dist/{index-678rwfc0.js → index-0924jp9m.js} +1 -1
  24. package/dist/{index-c4xqp05z.js → index-11grwjm1.js} +41 -41
  25. package/dist/index-1evqt03m.js +11 -0
  26. package/dist/{index-z5a4yxzz.js → index-1mppacnx.js} +3 -3
  27. package/dist/{index-jw1k4vbk.js → index-4qq083yd.js} +1 -1
  28. package/dist/{index-d5ysy1yn.js → index-5dysvvjv.js} +1 -1
  29. package/dist/{index-n7qyrdr1.js → index-5wpck4aw.js} +1 -1
  30. package/dist/{index-mtm8cfyt.js → index-8053zege.js} +2 -2
  31. package/dist/{index-5mw3eshk.js → index-8nqp3a4d.js} +1 -1
  32. package/dist/{index-2xs9cvjn.js → index-8sdrhr3q.js} +2 -2
  33. package/dist/{index-6mprnf7p.js → index-97mq40rr.js} +1 -1
  34. package/dist/{index-1hnw0rhc.js → index-9f52em7g.js} +29 -29
  35. package/dist/{index-0cn9bv8z.js → index-a4854mwz.js} +1 -1
  36. package/dist/{index-g8zv1gta.js → index-atp2ayra.js} +1 -1
  37. package/dist/{index-xjzmb1pn.js → index-b6x6a4xp.js} +2 -2
  38. package/dist/{index-yy1mm8zs.js → index-c7554sg7.js} +1 -1
  39. package/dist/{index-2gsarrbn.js → index-d1xjj001.js} +1 -1
  40. package/dist/{index-h8a8s8sn.js → index-ebwwtwwc.js} +1 -1
  41. package/dist/{index-8sm0nkh8.js → index-ep3zb271.js} +1 -1
  42. package/dist/index-gxgftnbh.js +26 -0
  43. package/dist/{index-g2raeeh4.js → index-h74va4wd.js} +2 -2
  44. package/dist/{index-v9fx5wab.js → index-hvjqgb97.js} +1 -1
  45. package/dist/{index-g3ap3xpr.js → index-jdh30t6c.js} +4 -4
  46. package/dist/{index-9bqd8veb.js → index-js1xn4sq.js} +3 -3
  47. package/dist/{index-x1h8r7pr.js → index-kt5zxp42.js} +1 -1
  48. package/dist/{index-ssjmzqcz.js → index-n6bdbgb9.js} +1 -1
  49. package/dist/{index-rdp5xq4r.js → index-nrsqzcfc.js} +1 -1
  50. package/dist/index-p23tet7a.js +2 -0
  51. package/dist/{index-04n4qgvd.js → index-pgew6sge.js} +3 -3
  52. package/dist/{index-1zw3kea7.js → index-qwtspxw8.js} +1 -1
  53. package/dist/index-rqq0k5fc.js +16 -0
  54. package/dist/{index-6jq17k9s.js → index-rv6h14n8.js} +1 -1
  55. package/dist/{index-qfz9fy56.js → index-rw9x93zb.js} +1 -1
  56. package/dist/{index-dm6yjmgq.js → index-rzpaqrhx.js} +2 -2
  57. package/dist/{index-vdahdt49.js → index-tgrt61qr.js} +1 -1
  58. package/dist/{index-ef95xr4z.js → index-thammzct.js} +2 -2
  59. package/dist/{index-tp4y9jde.js → index-wccxsz72.js} +1 -1
  60. package/dist/{index-scsjyj4m.js → index-x649afed.js} +2 -2
  61. package/dist/{index-8kvc8ttn.js → index-xrs52f2c.js} +1 -1
  62. package/dist/{index-yrgm89r8.js → index-ydc0tk17.js} +1 -1
  63. package/dist/{index-0248afsn.js → index-z5s398n0.js} +1 -1
  64. package/dist/index.js +2 -2
  65. package/dist/injections-x3xya90r.js +2 -0
  66. package/dist/interactive-qc1j66mq.js +2 -0
  67. package/dist/key.cmd-972133dv.js +2 -0
  68. package/dist/log-shipper-hjnn1d5p.js +2 -0
  69. package/dist/{path-utils-35re7qf9.js → path-utils-hxdyv2zn.js} +1 -1
  70. package/dist/{plugin-system-c916v9an.js → plugin-system-8hby8x1m.js} +1 -1
  71. package/dist/prereqs-runner-27x3j1md.js +2 -0
  72. package/dist/profile-mount-8dc9jwt5.js +2 -0
  73. package/dist/prune-stale-shims-23y0stm8.js +2 -0
  74. package/dist/register-core-qcj272qh.js +2 -0
  75. package/dist/secondary-profile-attach-xkvpmm08.js +2 -0
  76. package/dist/subprocess-1nna3d3x.js +2 -0
  77. package/dist/telemetry-8jfdyt51.js +2 -0
  78. package/dist/tree-sitter-javascript-q22gvtms.js +2 -0
  79. package/dist/tree-sitter-markdown-pntsjzm3.js +2 -0
  80. package/dist/tree-sitter-markdown_inline-g1wzqf7k.js +2 -0
  81. package/dist/tree-sitter-typescript-m9yfes10.js +2 -0
  82. package/dist/tree-sitter-zig-jmh62j90.js +2 -0
  83. package/dist/tunnel-bootstrap-5wgt9a1h.js +2 -0
  84. package/package.json +1 -1
  85. package/dist/app-jeyyhz7s.js +0 -2
  86. package/dist/bootstrap-workspace-zpm20zez.js +0 -2
  87. package/dist/bootstrap.service-pjmnpxha.js +0 -2
  88. package/dist/daemon-profile-vas1vf2t.js +0 -2
  89. package/dist/esm-9fpye77x.js +0 -2
  90. package/dist/gateway-client-43gzvj5s.js +0 -2
  91. package/dist/highlights-8d9mgr01.js +0 -2
  92. package/dist/highlights-jwvdxm9x.js +0 -2
  93. package/dist/highlights-qbx2vnme.js +0 -2
  94. package/dist/highlights-r3m83kn9.js +0 -2
  95. package/dist/highlights-s7mqapt6.js +0 -2
  96. package/dist/index-01qzsnwd.js +0 -16
  97. package/dist/index-5t4t0avg.js +0 -26
  98. package/dist/index-hrdamx5j.js +0 -2
  99. package/dist/index-tmrbs96r.js +0 -11
  100. package/dist/injections-srewsjcz.js +0 -2
  101. package/dist/interactive-22ta89hc.js +0 -2
  102. package/dist/key.cmd-wgcq6kt8.js +0 -2
  103. package/dist/log-shipper-k24m8yw5.js +0 -2
  104. package/dist/prereqs-runner-ca4kt803.js +0 -2
  105. package/dist/profile-mount-npcknw6v.js +0 -2
  106. package/dist/prune-stale-shims-nkx9vq5m.js +0 -2
  107. package/dist/register-core-mbv4hrbv.js +0 -2
  108. package/dist/secondary-profile-attach-db5cr3e1.js +0 -2
  109. package/dist/subprocess-g9sk1ep9.js +0 -2
  110. package/dist/telemetry-tnq47dcs.js +0 -2
  111. package/dist/tree-sitter-javascript-3h25c6bs.js +0 -2
  112. package/dist/tree-sitter-markdown-3nemcjhe.js +0 -2
  113. package/dist/tree-sitter-markdown_inline-16ftwa53.js +0 -2
  114. package/dist/tree-sitter-typescript-f6mq6ze6.js +0 -2
  115. package/dist/tree-sitter-zig-s2trkm2d.js +0 -2
  116. package/dist/tunnel-bootstrap-2kg79ng8.js +0 -2
@@ -1,6 +1,6 @@
1
1
  // @bun
2
- import{L as r1}from"./index-2gsarrbn.js";import{M as b2}from"./index-b5dhmybd.js";import{O as a$,P as B1}from"./index-e1bw1bwr.js";import{$ as U2,Q as r$,R as c$,S as s0,T as r0,U as e$,V as e0,W as $0,X as $1,Y as D$,Z as E$,_ as J2,ca as z0,da as I2,ea as _2,fa as K0,ga as U1,ha as I1,ia as _1,ja as L2,ka as W0}from"./index-g8zv1gta.js";import{la as J$,ma as X$,na as B$,oa as Q1,ta as w2}from"./index-qfz9fy56.js";import{va as o}from"./index-ssjmzqcz.js";import{Ca as X2}from"./index-4wgjx8bf.js";import{Ea as t1,Fa as k$,Ha as o$,Ma as t0,Oa as s1,Pa as g2,Wa as s$}from"./index-g3ap3xpr.js";import{Xa as l}from"./index-0ckffygp.js";import{Ya as d1,ab as a}from"./index-rc79x8fw.js";import{db as P2}from"./index-52cp759f.js";import{Ib as M2}from"./index-01qzsnwd.js";import{gc as t$,hc as T$,ic as f,jc as b,kc as B,lc as q0}from"./index-5mw3eshk.js";import{Bc as x$,Cc as W$,Dc as u$,nc as K,oc as N,pc as V,qc as C,rc as U,sc as j,tc as W,uc as T,vc as _,wc as J,xc as n,yc as G$}from"./index-z5a4yxzz.js";import{Ec as b0,Fc as e,Gc as v$}from"./index-ef95xr4z.js";import{Kc as M,Mc as S,Nc as y,Oc as m,Pc as L0,Qc as P$}from"./index-xjzmb1pn.js";import{Rc as Z2,Tc as A0,Uc as a1,Wc as G2,Xc as f0,Zc as y$,ad as F2,bd as f$,cd as P0,dd as T2,ed as V0,fd as R2,gd as j2,hd as E2,id as N2,kd as B0,ld as O1,nd as q$,pd as U$,td as a0}from"./index-g2raeeh4.js";import{Nd as c0,zd as O0}from"./index-9bqd8veb.js";import{$d as V$,Xd as Y0,_d as Q$,ae as N$,be as Z$}from"./index-0cn9bv8z.js";import{he as Y$}from"./index-yy1mm8zs.js";import{existsSync as o0}from"fs";import{join as p2}from"path";import{createServer as n2}from"net";function i2(Y,q="0.0.0.0"){return new Promise(($)=>{let Z=n2();Z.once("error",()=>$(!1)),Z.once("listening",()=>{Z.close(()=>$(!0))}),Z.listen({host:q,port:Y,exclusive:!0})})}async function p0(Y,q="0.0.0.0"){let $=Y;while(!await i2($,q))if($++,$>65535)throw Error(`No free port found starting from ${Y}`);return $}function Y1(Y){Y.command("start").description("Start a VibeControls agent instance").option("-p, --port <port>","Port to listen on. Default: 3005 for the 'default' profile, deterministic 3100-3399 for any other profile (FNV-1a hash) so multiple profiles run side-by-side without EADDRINUSE.").option("-n, --name <name>","Agent instance name","default").option("-f, --foreground","Run in foreground mode (default: daemon)",!1).option("--db-path <path>","Path to the agent storage directory").option("--profile <profile>","Profile name for isolated config (env: VIBECONTROLS_PROFILE)").option("--host <host>","Host to bind to","0.0.0.0").option("--skip-plugin-install","Skip automatic installation of default plugins",!1).option("--skip-plugin <name>","Skip a specific default plugin (repeatable). Accepts the short pluginName or the full package name.",(q,$=[])=>[...$,q],[]).option("--no-install-deps","Skip auto-installing missing tools (installed by their plugins on start by default)").option("-y, --yes","Skip the first-run install consent prompt. Equivalent to VIBE_AUTO_ACCEPT=1; useful for CI / Docker / nohup contexts.",!1).option("--client-id <id>","Gateway OAuth client ID (env: VIBE_CLIENT_ID)").option("--client-secret <secret>","Gateway OAuth client secret (env: VIBE_CLIENT_SECRET)").option("--global-gateway-url <url>","Global gateway URL (env: VIBE_GLOBAL_GATEWAY_URL)").option("--workspace-gateway-url <url>","Workspace gateway URL (env: VIBE_WORKSPACE_GATEWAY_URL)").option("--workspace-id <id>","Workspace ID for auto-report (env: VIBE_WORKSPACE_ID)").option("--isolate <plugins>","Comma-separated list of plugin names to force into worker_threads isolation (Phase 4 hostile-plugin mode). Sets VIBE_ISOLATE_PLUGINS in the daemon env.").option("--profiles <names>","Comma-separated list of profiles to host in this daemon (multi-profile boot). When unset, the daemon hosts a single profile resolved via --profile / VIBECONTROLS_PROFILE / 'default'. Sets VIBECONTROLS_PROFILES in the daemon env so app boot can spin up additional ProfileContexts via the in-process registry.").option("--strict-key-fetch","Refuse to boot if any profile's encryption-key fetch fails. Default lenient: a failed profile is marked degraded and the daemon stays up. Sets VIBE_STRICT_KEY_FETCH=1 in the daemon env.",!1).option("--json","Emit JSON").option("--plain","Plain text output (no interactive TUI). Implied for non-TTY / CI.").option("--abilities <list>","Comma-separated ability keys to install non-interactively (e.g. session,ai,gitops). Storage/tunnel/backup are always included.").option("--providers <list>","Comma-separated extra provider plugins to install beyond each meta's default (e.g. session-wezterm,ai-claude). Accepts short names or @vibecontrols/... packages. Persisted; manage later with `vibe capability`.").option("--wait-ready [seconds]","Block until the agent is fully ready (or fails). Polls /health/ready and renders phase transitions live. Without a value, defaults to 60s. Exits non-zero if the agent ends up degraded or times out. Useful for scripts/CI.").option("--no-wait","Skip the phase tracker entirely after spawning the daemon. Restores the old fire-and-print behavior \u2014 for users who want the previous quick-return UX.").action(async function(q){let $={...Y.opts(),...q};try{let E=function(h){if(h==="default")return 3005;let d=2166136261;for(let g=0;g<h.length;g++)d=Math.imul(d^h.charCodeAt(g),16777619);return 3100+Math.abs(d)%300},Z=new o,X=q.profile||process.env.VIBECONTROLS_PROFILE||"default";if(process.env.VIBECONTROLS_PROFILE=X,typeof q.isolate==="string"&&q.isolate.length>0)process.env.VIBE_ISOLATE_PLUGINS=q.isolate;if(typeof q.profiles==="string"&&q.profiles.length>0){let h=q.profiles.split(",").map((d)=>d.trim()).filter(Boolean);if(h.length>0){if(process.env.VIBECONTROLS_PROFILES=h.join(","),process.env.VIBECONTROLS_PROFILE=h[0],h.length>1)j(`--profiles received ${h.length} entries; daemon boots with '${h[0]}'. Remaining (${h.slice(1).join(", ")}) will be attached via /api/profiles after listen.`)}}if(q.strictKeyFetch===!0)process.env.VIBE_STRICT_KEY_FETCH="1";a0();let H=q.dbPath||N$(),Q=Z$(),z=!o0(H)&&!o0(p2(Q,"agents.json")),L=f($),I=L!=="json"&&L!=="plain"&&t$()&&q.yes!==!0,O=r$(Q),G;if(typeof $.abilities==="string"&&$.abilities.trim()!=="")G=e0($.abilities);else if(O!==null)G=O;else if(I)G=await e$();else G=$0();let x=typeof $.providers==="string"&&$.providers.trim()!=="",F=x?s0($.providers):c$(Q);if(O===null){let h=r0({installDeps:q.installDeps===!0,skipPluginInstall:q.skipPluginInstall===!0,skipPlugins:Array.isArray(q.skipPlugin)?q.skipPlugin:[]},G);if(z&&h.plugins.length>0)J(),W(`Installing ${h.plugins.length} plugin(s) for the selected abilities.`),J();$1(Q,h,G,process.env.VIBE_AGENT_VERSION,F)}else if(x)D$(Q,{providers:F,agentVersion:process.env.VIBE_AGENT_VERSION});if((z||x)&&F.length>0&&q.skipPluginInstall!==!0){W(`Installing ${F.length} selected provider plugin(s)...`);try{let{PluginManager:h}=await import("./plugin-system-c916v9an.js"),d=new h;for(let g of F)try{await d.install(g),U(`Installed provider ${g}`)}catch(u){j(`Could not install provider ${g}: ${u instanceof Error?u.message:String(u)}`)}}catch(h){j(`Provider install skipped: ${h instanceof Error?h.message:String(h)}`)}J()}if(z){W("First run detected \u2014 running setup..."),J();let h=Array.isArray(q.skipPlugin)?q.skipPlugin:[],d=q.skipPluginInstall?[]:o$(process.platform,G).filter((r)=>!h.includes(r.packageName)&&!h.includes(r.pluginName)).map((r)=>r.packageName),g=t0(d),K$=a$(g).filter((r)=>!r.installed);if(K$.length>0)if(j(`Missing tools: ${K$.map((r)=>r.name).join(", ")}`),q.installDeps)W("Their plugins will install them automatically on startup.");else W("Auto-install skipped (`--no-install-deps`) \u2014 install them yourself or drop the flag.");else U("All plugin tools present.");J()}if(!q.skipPluginInstall){let h=Array.isArray(q.skipPlugin)?q.skipPlugin:[],d=new s$;await d.loadCorePlugins(),await d.loadAll();let g=await d.ensureDefaultPlugins((u)=>{if(u.startsWith("No "))j(u);else if(u.startsWith("Installed "))U(u);else if(u.startsWith("Failed "))j(u);else W(u)},h,G);if(g.length>0)U(`Auto-installed ${g.length} default plugin${g.length>1?"s":""}.`),J()}let R=q.profile||process.env.VIBECONTROLS_PROFILE||q.name||"default",w=q.port?parseInt(q.port,10):E(R);if(isNaN(w)||w<1||w>65535)V("Invalid port number. Must be between 1 and 65535.");let D=await p0(w);if(D!==w)j(`Port ${w} is in use. Auto-selecting port ${K.bold(String(D))} instead.`),w=D;let A=q.host,s=`http://${A==="0.0.0.0"?"localhost":A}:${w}`,p=q.clientId||process.env.VIBE_CLIENT_ID,v=q.clientSecret||process.env.VIBE_CLIENT_SECRET,P=q.globalGatewayUrl||process.env.VIBE_GLOBAL_GATEWAY_URL,c=q.workspaceGatewayUrl||process.env.VIBE_WORKSPACE_GATEWAY_URL,O$=q.workspaceId||process.env.VIBE_WORKSPACE_ID;if(p&&!v)V("--client-secret is required when --client-id is provided.");if(v&&!p)V("--client-id is required when --client-secret is provided.");if(p&&v){if(!P&&!process.env.VIBE_GLOBAL_GATEWAY_URL)V("--global-gateway-url is required when providing client credentials (none set in env).");if(process.env.VIBE_CLIENT_ID=p,process.env.VIBE_CLIENT_SECRET=v,P)process.env.VIBE_GLOBAL_GATEWAY_URL=P;let{writeAgentConfig:h}=await import("./agent-config-85pskv43.js");if(h({clientId:p,clientSecret:v,workspaceId:O$,globalGatewayUrl:P,workspaceGatewayUrl:c}),c)process.env.VIBE_WORKSPACE_GATEWAY_URL=c;if(O$)process.env.VIBE_WORKSPACE_ID=O$;U("Gateway credentials staged in env. Agent will authenticate and persist them on startup."),J()}else if(c||O$||P){if(j("Workspace options provided without --client-id / --client-secret \u2014 they will be staged in env but unused until credentials are configured."),c)process.env.VIBE_WORKSPACE_GATEWAY_URL=c;if(O$)process.env.VIBE_WORKSPACE_ID=O$;if(P)process.env.VIBE_GLOBAL_GATEWAY_URL=P;J()}if(q.foreground){if(!$.json)T("Starting agent in foreground"),_("Name",q.name),_("Port",String(w)),_("Host",A),_("Database",H),J();let{bootstrapWorkspace:h}=await import("./bootstrap-workspace-zpm20zez.js");h();let{createApp:d}=await import("./app-jeyyhz7s.js"),g=await d({port:w,host:A,dbPath:H});if(await g.start(),p&&v&&O$&&P&&c){let K$=await g.finalize({clientId:p,clientSecret:v,workspaceId:O$,globalGatewayUrl:P,workspaceGatewayUrl:c});if(!K$.ok)j(`Finalize failed \u2014 agent remains in awaiting-config state: ${K$.error}`)}if(B($,{ok:!0,name:q.name,port:w,host:A,pid:process.pid,url:s}));else await u$(s);let u=async()=>{await g.stop(),process.exit(0)};process.on("SIGTERM",u),process.on("SIGINT",u)}else{if(!$.json)T("Starting agent in daemon mode"),_("Name",q.name),_("Port",String(w)),_("Host",A),_("Database",H),J();if(q.installDeps===!1)process.env.VIBE_SKIP_PREREQ_INSTALL="1";await Z.startDaemon({port:w,name:q.name,daemon:!0,dbPath:H,host:A,profile:X});let d=(await Z.getStatus(q.name))?.port??w,u=`http://${A==="0.0.0.0"?"localhost":A}:${d}`,K$=q.waitReady,r=q.wait===!1,l0=K$!==void 0;if(r&&l0)j("--wait-ready is ignored because --no-wait was also passed.");let p$=!r&&l0,n0=!r&&(p$||!$.json),i0=(()=>{let C$=typeof K$==="string"?Number.parseInt(K$,10):NaN;if(Number.isInteger(C$)&&C$>0)return C$*1000;return p$?60000:25000})();if($.json){if(n0){let{trackAgentReady:C$}=await import("./agent-ready-tracker-zp6p8e6f.js"),$$=await C$(u,{timeoutMs:i0,verbose:!1});if(p$&&($$.outcome==="degraded"||$$.outcome==="timeout"))process.exitCode=1;B($,{ok:$$.outcome==="ready"||$$.outcome==="awaiting-config",name:q.name,port:d,host:A,url:u,abilities:[...G],outcome:$$.outcome,bootState:$$.bootState,degradedReasons:$$.degradedReasons,summary:$$.summary})}else B($,{ok:!0,name:q.name,port:d,host:A,url:u});return}if(await u$(u),n0){let{trackAgentReady:C$}=await import("./agent-ready-tracker-zp6p8e6f.js");J();let $$=await C$(u,{timeoutMs:i0,verbose:!0});if(p$&&($$.outcome==="degraded"||$$.outcome==="timeout"))process.exitCode=1}}}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}V(`Failed to start agent: ${X}`)}})}function q1(Y){Y.command("stop").description("Stop a running VibeControls agent instance").option("-n, --name <name>","Agent instance name","default").option("--all","Stop all running agent instances",!1).option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=new o;if(q.all){let X=await Z.listInstances();if(!X||X.length===0){if(B($,{ok:!0,stopped:[]}))return;T("Stopping all agent instances"),J(),W(`${N.info} No running agent instances found.`);return}let H=[];if(!$.json)T("Stopping all agent instances"),J();for(let Q of X)try{if(await Z.stop(Q.name),H.push(Q.name),!$.json)U(`${N.success} Stopped ${K.bold(Q.name)}`)}catch{if(!$.json)V(`Failed to stop ${K.bold(Q.name)}`)}if(B($,{ok:!0,stopped:H,total:X.length}))return;J(),U(`${N.success} Stopped ${H.length}/${X.length} instance(s).`)}else{if(await Z.stop(q.name),B($,{ok:!0,name:q.name}))return;T(`Stopping agent: ${q.name}`),J(),U(`${N.success} Agent ${K.bold(q.name)} stopped.`)}}catch(Z){if($.json){B($,{ok:!1,error:C(Z)});return}V(`Failed to stop agent: ${C(Z)}`)}})}function Z1(Y){Y.command("restart").description("Restart a running VibeControls agent instance").option("-n, --name <name>","Agent instance name","default").option("-p, --port <port>","Port to listen on").option("--db-path <path>","Path to the agent storage directory").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=new o;if(!$.json)T(`Restarting agent: ${q.name}`),J(),W(`${N.info} Stopping agent ${K.bold(q.name)}...`);let X=await Z.getStatus(q.name);try{if(await Z.stop(q.name),!$.json)U(`${N.success} Agent stopped.`)}catch{if(!$.json)W(`${N.info} Agent was not running.`)}let H=q.port??X?.port??3005,Q=typeof H==="number"?H:parseInt(H,10);if(isNaN(Q)||Q<1||Q>65535){if($.json){B($,{ok:!1,error:"Invalid port number"});return}V("Invalid port number. Must be between 1 and 65535.");return}let z={port:Q,name:q.name,daemon:!0,dbPath:q.dbPath??X?.config?.dbPath??N$(),host:X?.config?.host,profile:X?.config?.profile};if(!$.json)J(),W(`${N.info} Starting agent ${K.bold(q.name)}...`);await Z.startDaemon(z);let L=`http://localhost:${Q}`;if(B($,{ok:!0,name:q.name,port:Q,url:L}))return;J(),U(`${N.success} Agent ${K.bold(q.name)} restarted.`),J(),_("Port",String(Q)),_("Database",z.dbPath),J(),u$(L)}catch(Z){if($.json){B($,{ok:!1,error:C(Z)});return}V(`Failed to restart agent: ${C(Z)}`)}})}import{existsSync as o2,readFileSync as a2,unlinkSync as X1}from"fs";import{join as z1}from"path";function t2(Y){let q=z1(V$(),Y,"runtime.json");if(!o2(q))return null;try{let $=JSON.parse(a2(q,"utf8"));if(typeof $.pid!=="number")return null;return{...$,pid:$.pid,path:q}}catch{return null}}async function H1(Y){let q=t2(Y);if(!q)return null;if(!B$(q.pid)){try{X1(q.path)}catch{}return`agent pid=${q.pid} (${Y}) already gone (cleaned runtime.json).`}let $=l();if(!$.killProcessTree(q.pid,"SIGTERM"))return`failed to SIGTERM agent pid=${q.pid}.`;if(await new Promise((Z)=>setTimeout(Z,3000)),B$(q.pid))$.killProcessTree(q.pid,"SIGKILL");try{X1(q.path)}catch{}return`agent ${Y} pid=${q.pid}${q.port?` (port ${q.port})`:""} killed.`}async function s2(Y){let q=z1(V$(),Y),$=J$(q);if(!$)return null;if(!B$($.pid))return X$(q),`tunnel pid=${$.pid} already gone (cleaned state).`;let Z=l();if(!Z.killProcessTree($.pid,"SIGTERM"))return`failed to SIGTERM tunnel pid=${$.pid}.`;if(await new Promise((X)=>setTimeout(X,3000)),B$($.pid))Z.killProcessTree($.pid,"SIGKILL");return X$(q),`tunnel ${$.provider} pid=${$.pid} (${$.url??"no url"}) killed.`}function W1(Y){Y.command("kill").description("Force-kill an agent instance and its tunnel. Defaults to active profile.").option("-n, --name <name>","Agent instance name (alias of --profile, kept for back-compat)").option("--profile <name>","Kill a specific profile (overrides --name and VIBECONTROLS_PROFILE)").option("--all","Kill every agent instance and every profile's tunnel",!1).option("-y, --yes","Skip the confirmation prompt (for scripts/CI)",!1).option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q},Z=q.all?"ALL agent instances + every profile's tunnel":`agent '${$.profile??$.name??"active profile"}'`;if(!await q0($,`Force-kill ${Z}? This sends SIGKILL (no graceful shutdown).`)){W("Aborted.");return}let X=[];try{let H=new o;if(q.all){if(!$.json)T("Force killing all agent instances + tunnels"),J();let I=await H.listInstances()??[],O=0,G=new Set;for(let R of I)try{if(await H.kill(R.name),!$.json)U(`${N.success} agent ${K.bold(R.name)} (pid=${R.pid||"?"}) killed.`);X.push(R.name),O++,G.add(R.name)}catch{if(!$.json)j(`${N.warning} could not kill agent ${R.name}.`)}try{let R=await import("fs"),E=V$(),w=R.existsSync(E)?R.readdirSync(E):[];for(let D of w){if(G.has(D))continue;let A=await H1(D);if(A)U(`${N.success} ${A}`),O++}}catch(R){j(`${N.warning} runtime.json sweep failed: ${R instanceof Error?C(R):String(R)}`)}let x=Q1({allProfiles:!0}),F=0;for(let R of x){if(!R.alive){X$(R.profileDir);continue}let E=l();if(E.killProcessTree(R.pid,"SIGTERM"),await new Promise((w)=>setTimeout(w,3000)),B$(R.pid))E.killProcessTree(R.pid,"SIGKILL");X$(R.profileDir),U(`${N.success} tunnel ${R.provider} pid=${R.pid} (${R.url??"no url"}, ${R.profileDir.split("/").pop()}) killed.`),F++}if(B($,{ok:!0,killed:X,tunnels:F}))return;J(),U(`${N.success} killed ${O} agent(s) and ${F} tunnel(s).`);return}let Q=q.profile||q.name||Y0();if(!$.json)T(`Force killing profile: ${Q}`),J();let z=await H.getStatus(Q);if(z){if(await H.kill(Q),X.push(Q),!$.json)U(`${N.success} agent ${K.bold(Q)} pid=${z.pid||"?"} killed.`)}else{let I=await H1(Q);if(I){if(X.push(Q),!$.json)U(`${N.success} ${I}`)}else if(!$.json)W(`${N.info} no running agent service for profile ${Q}.`)}let L=await s2(Q);if(L){if(!$.json)U(`${N.success} ${L}`)}else if(!$.json)W(`${N.info} no tunnel recorded for profile ${Q}.`);B($,{ok:!0,killed:X})}catch(H){if($.json){B($,{ok:!1,error:C(H)});return}V(`Failed to kill: ${C(H)}`)}})}function K1(Y){Y.command("list").alias("ls").description("List all VibeControls agent instances").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function(q){try{let $={...Y.opts(),...q},Z=new o;await b({mode:f($),fetchData:()=>Z.listInstances(),plain:(X)=>{if(T("Agent Instances"),J(),!X||X.length===0){W(`${N.info} No agent instances found.`),W(`Run ${K.bold("vibe start")} to start an agent.`);return}let H=X.map((L)=>({Name:L.name,Status:x$(L.status),PID:L.pid||"-",Port:L.port||"-",Host:L.config?.host||"-",Database:L.config?.dbPath||"-",Started:L.startTime?G$(L.startTime):"-"}));n(H),J();let Q=X.filter((L)=>L.status==="running").length,z=X.length-Q;W(`${N.info} ${X.length} instance(s): ${K.green(String(Q))} running, ${K.dim(String(z))} stopped`)},interactive:async(X)=>{if(!X||X.length===0){T("Agent Instances"),J(),W(`${N.info} No agent instances found.`),W(`Run ${K.bold("vibe start")} to start an agent.`);return}let H=X.map((Q)=>{let z=[`${K.bold(Q.name)} ${x$(Q.status)}`,"",` PID: ${Q.pid??"-"}`,` Port: ${Q.port??"-"}`,` Host: ${Q.config?.host??"-"}`,` Database: ${Q.config?.dbPath??"-"}`,` Started: ${Q.startTime?G$(Q.startTime):"-"}`];return{id:Q.name,label:Q.name,hint:Q.status==="running"?"running":"stopped",detail:z.join(`
3
- `)}});await e({title:`vibe list \u2014 ${X.length} instance(s)`,rows:H,footer:"\u2191/\u2193 navigate \xB7 q to quit"})},json:(X)=>X.map((H)=>({name:H.name,status:H.status,pid:H.pid??null,port:H.port??null,host:H.config?.host??null,database:H.config?.dbPath??null,startTime:H.startTime??null}))})}catch($){V(`Failed to list instances: ${$.message}`)}})}var V1=5000;function L1(Y){Y.command("logs").description("View logs for a VibeControls agent instance").option("-n, --name <name>","Agent instance name","default").option("-f, --follow","Follow log output",!1).option("--tail <lines>","Number of lines to show from the end","100").option("--json","Emit JSON (one object per line, banners suppressed)").option("--plain","Force plain text output").action(async function(q){try{let $={...Y.opts(),...q},Z=new o,X=parseInt($.tail??"100",10);if(isNaN(X)||X<1||X>V1){V(`Invalid tail value. Must be between 1 and ${V1}.`);return}let H=$.name??"default";if(!await Z.getStatus(H)){V(`Agent instance ${K.bold(H)} not found.`);return}if(!$.json){if($.follow)T(`Following logs: ${H}`),W(`${N.info} Press Ctrl+C to stop following.`);else T(`Logs: ${H}`);J()}await Z.showLogs(H,{follow:!!$.follow,tail:X})}catch($){V(`Failed to get logs: ${C($)}`)}})}function J1(Y){Y.command("setup").description("Install system dependencies and (optionally) write gateway auth config").option("--check","Only check dependencies without installing",!1).option("--client-id <id>","OAuth app client ID (for backend authentication)").option("--client-secret <secret>","OAuth app client secret").option("--workspace-id <id>","Workspace UUID this agent belongs to").option("--global-gateway-url <url>","Global public gateway URL (default: http://localhost:4000/global/graphql)").option("--workspace-gateway-url <url>","Workspace gateway URL (default: http://localhost:4001/workspaces/graphql)").option("--storage-adapter <name>","Named storage adapter (default: skalex, or custom:<path>)").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q},Z=[];try{if(!$.json)T("VibeControls Agent Setup");let X={};if(q.clientId)X.clientId=q.clientId;if(q.clientSecret)X.clientSecret=q.clientSecret;if(q.workspaceId)X.workspaceId=q.workspaceId;if(q.globalGatewayUrl)X.globalGatewayUrl=O0(q.globalGatewayUrl,"globalGatewayUrl");if(q.workspaceGatewayUrl)X.workspaceGatewayUrl=O0(q.workspaceGatewayUrl,"workspaceGatewayUrl");if(q.storageAdapter)X.storageAdapter=q.storageAdapter;if(Object.keys(X).length>0){let O=U$(X);if(Z.push(...Object.keys(X)),!$.json){U(`Agent config written to ${B0()}`),_("clientId",O.clientId?K.dim("(set)"):K.dim("(unset)")),_("clientSecret",O.clientSecret?K.dim("(set)"):K.dim("(unset)")),_("workspaceId",O.workspaceId??K.dim("(unset)"));let G=O1();if(_("globalGatewayUrl",O.globalGatewayUrl??G.globalGatewayUrl),_("workspaceGatewayUrl",O.workspaceGatewayUrl??G.workspaceGatewayUrl),O.storageAdapter)_("storageAdapter",O.storageAdapter);J()}}else{let O=q$();if((O.clientId||O.clientSecret||O.workspaceId)&&!$.json)W(`Using existing agent config at ${B0()} (pass --client-id/--client-secret/--workspace-id to update).`),J()}if(!$.json)W("Checking dependencies..."),J();let H=a$(),Q=[],z=[];for(let O of H){if(O.installed)z.push(O.name);if(!$.json){let G=O.installed?N.success:N.error,x=O.version?K.dim(` (${O.version})`):"",F=O.required?"":K.dim(" [optional]");_(`${G} ${O.name}`,`${O.installed?K.green("installed"):K.red("missing")}${x}${F}`)}if(!O.installed)Q.push(O.name)}if(!$.json)J();if(Q.length===0){if(B($,{ok:!0,installed:z,configured:Z}))return;U("All dependencies are installed.");return}if(q.check){if($.json){B($,{ok:!1,installed:z,missing:Q,configured:Z});return}j(`Missing: ${Q.join(", ")}`),W(`Run ${K.bold("vibe setup")} to install them.`),process.exit(1)}if(!$.json)W(`Installing missing dependencies: ${Q.join(", ")}...`),J();let L=await B1(Q),I=Q.filter((O)=>!L.failed.includes(O));if(L.failed.length>0){if($.json){B($,{ok:!1,installed:[...z,...I],failed:L.failed,configured:Z});return}j(`${L.failed.length} tool(s) failed: ${L.failed.join(", ")}`),W("You may need to install manually or use sudo."),process.exit(1)}else{if(B($,{ok:!0,installed:[...z,...I],configured:Z}))return;U("All dependencies installed successfully.")}}catch(X){let H=X instanceof Error?C(X):String(X);if($.json){B($,{ok:!1,error:H});return}V(`Setup failed: ${H}`)}})}function r2(Y){let q=l();return q.which(Y)??`${Y}${q.executableSuffix}`}function C1(Y){Y.command("update").description("Check for and install VibeControls agent updates").option("--check","Only check for updates without installing",!1).option("--allow-incompatible","Override engines.bun compatibility check (use with care)",!1).option("--no-restart","Skip the post-install idle-aware restart of any running agent").option("-n, --name <name>","Agent profile name to restart after update","default").option("--version-target <version>","Install a specific version instead of the latest (e.g. 2026.601.21)").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{if(!$.json)T("VibeControls Agent Update"),J(),W(`${N.info} Checking for updates...`),J();let Z=await I1();if(Z.error&&!Z.latest){if(B($,{ok:!1,current:Z.current,error:Z.error}))return;V(Z.error);return}if(!$.json)_("Package",K.bold(Z.name)),_("Registry",K.bold(Z.registry)),_("Current version",K.bold(Z.current)),_("Latest version",K.bold(Z.latest??"unknown")),J();if(q.check){if(B($,{ok:!0,current:Z.current,latest:Z.latest,upToDate:!Z.hasUpdate}))return;if(!Z.hasUpdate)U(`${N.success} You are running the latest version.`);else j(`${N.warning} A new version is available: ${K.green(Z.latest??"")}`),W(`${N.info} Run ${K.bold("vibe update")} to install the update.`);return}let X=q.versionTarget;if(!X&&!Z.hasUpdate){if(B($,{ok:!0,current:Z.current,latest:Z.latest,upToDate:!0}))return;U(`${N.success} You are running the latest version.`);return}if(!$.json)W(`${N.info} Updating to ${K.bold(X??Z.latest??"latest")}...`),J();let H=await _1({targetVersion:X,allowIncompatible:!!q.allowIncompatible,restart:q.restart!==!1,name:q.name,onLog:$.json?void 0:(Q)=>W(`${N.info} ${Q}`)});if(!H.ok){if(B($,{ok:!1,current:H.current,previous:H.previous,latest:H.latest,rolledBack:H.rolledBack,error:H.error}))return;V(H.error??"Update failed.");return}if(!$.json)switch(H.restart){case"restarted":U(`${N.success} Restarted agent ${K.bold(q.name)} on the new version.`);break;case"not-running":W(`${N.info} No running agent for profile ${K.bold(q.name)}; nothing to restart.`);break;case"still-busy":j(`${N.warning} Agent still serving requests \u2014 run ${K.bold("vibe restart")} when it's quiet.`);break;case"error":j(`${N.warning} Auto-restart failed: ${H.restartError}. Run ${K.bold("vibe restart")} manually.`);break}if(B($,{ok:!0,current:H.current,previous:H.previous,latest:H.latest,updated:H.updated,restart:H.restart,...H.restartError?{restartError:H.restartError}:{}}))return;if(J(),H.updated)U(`${N.success} Updated to ${K.bold(H.current)} (smoke: ${H.smoke?.step??"ok"}).`);else U(`${N.success} You are running the latest version.`);if(q.restart===!1)W(`${N.info} --no-restart set \u2014 restart running agents manually for the update to take effect.`)}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}V(`Update failed: ${X}`)}}),Y.command("rollback").description("Roll the global agent install back to a specific version").argument("<version>","Target CalVer version (e.g. 2026.428.3)").action(async(q)=>{try{T("VibeControls Agent Rollback");let $=await U1();if(_("Package",K.bold($.name)),_("Current version",K.bold($.version)),_("Target version",K.bold(q)),J(),W(`${N.info} Rolling back\u2026`),Bun.spawnSync([r2("npm"),"install","-g",`${$.name}@${q}`,`--registry=${$.registry}`],{stdout:"inherit",stderr:"inherit"}).exitCode!==0){V("Rollback failed.");return}U(`${N.success} Rolled back to ${K.bold(q)}.`)}catch($){V(`Rollback failed: ${$ instanceof Error?C($):String($)}`)}})}import{existsSync as F$,mkdirSync as e2,writeFileSync as I0,unlinkSync as $6,readFileSync as J0}from"fs";import{join as L$}from"path";import{homedir as M$}from"os";var Y6=/^[A-Za-z0-9][A-Za-z0-9:_-]{0,63}$/,q6=/^--[A-Za-z0-9][A-Za-z0-9-]{0,63}$/;function R1(Y){return Y6.test(Y)?Y:null}function j1(Y){return Y.filter((q)=>R1(q))}function Z6(Y){return Y.filter((q)=>q6.test(q))}function w$(Y){return Y.commands.flatMap((q)=>{let $=R1(q.name());if(!$)return[];return[{name:$,description:q.description()||"",options:q.options.map((Z)=>({flags:Z.flags,description:Z.description||""})),subcommands:w$(q)}]})}function X6(Y){return j1(Y.map((q)=>q.name))}function H6(Y,q){let $=Y.find((X)=>X.name===q);if(!$)return[];let Z=[];for(let X of $.options){let H=X.flags.match(/--([\w-]+)/);if(H)Z.push(`--${H[1]}`)}return Z6(Z)}function E1(Y){let q=X6(Y),Z=Y.filter((H)=>H.subcommands.length>0).map((H)=>({name:H.name,subs:j1(H.subcommands.map((Q)=>Q.name))})).map((H)=>` ${H.name})
2
+ import{L as r1}from"./index-d1xjj001.js";import{M as b2}from"./index-b5dhmybd.js";import{O as a$,P as B1}from"./index-e1bw1bwr.js";import{$ as U2,Q as r$,R as c$,S as s0,T as r0,U as e$,V as e0,W as $0,X as $1,Y as D$,Z as E$,_ as J2,ca as z0,da as I2,ea as _2,fa as K0,ga as U1,ha as I1,ia as _1,ja as L2,ka as W0}from"./index-atp2ayra.js";import{la as J$,ma as X$,na as B$,oa as Q1,ta as w2}from"./index-rw9x93zb.js";import{va as p}from"./index-n6bdbgb9.js";import{Ca as X2}from"./index-4wgjx8bf.js";import{Ea as t1,Fa as k$,Ha as o$,Ma as t0,Oa as s1,Pa as g2,Wa as s$}from"./index-jdh30t6c.js";import{Xa as l}from"./index-0ckffygp.js";import{Ya as d1,ab as a}from"./index-rc79x8fw.js";import{db as P2}from"./index-52cp759f.js";import{Ib as M2}from"./index-rqq0k5fc.js";import{hc as t$,ic as T$,jc as f,kc as P,lc as B,mc as q0}from"./index-8nqp3a4d.js";import{Cc as x$,Dc as W$,Ec as u$,oc as K,pc as E,qc as L,rc as C,sc as U,tc as j,uc as W,vc as T,wc as I,xc as J,yc as n,zc as G$}from"./index-1mppacnx.js";import{Fc as b0,Gc as r,Hc as v$}from"./index-thammzct.js";import{Lc as w,Nc as A,Oc as y,Pc as m,Qc as L0,Rc as P$}from"./index-b6x6a4xp.js";import{Sc as Z2,Uc as A0,Vc as a1,Xc as G2,Yc as f0,_c as y$,bd as F2,cd as f$,dd as P0,ed as T2,fd as V0,gd as R2,hd as j2,id as E2,jd as N2,ld as B0,md as O1,od as Y$,qd as U$,ud as a0}from"./index-h74va4wd.js";import{Ad as O0,Od as c0}from"./index-js1xn4sq.js";import{$d as Q$,Yd as Y0,ae as V$,be as N$,ce as Z$}from"./index-a4854mwz.js";import{ie as $$}from"./index-c7554sg7.js";import{existsSync as o0}from"fs";import{join as p2}from"path";import{createServer as n2}from"net";function i2(Y,q="0.0.0.0"){return new Promise(($)=>{let Z=n2();Z.once("error",()=>$(!1)),Z.once("listening",()=>{Z.close(()=>$(!0))}),Z.listen({host:q,port:Y,exclusive:!0})})}async function p0(Y,q="0.0.0.0"){let $=Y;while(!await i2($,q))if($++,$>65535)throw Error(`No free port found starting from ${Y}`);return $}function Y1(Y){Y.command("start").description("Start a VibeControls agent instance").option("-p, --port <port>","Port to listen on. Default: 3005 for the 'default' profile, deterministic 3100-3399 for any other profile (FNV-1a hash) so multiple profiles run side-by-side without EADDRINUSE.").option("-n, --name <name>","Agent instance name","default").option("-f, --foreground","Run in foreground mode (default: daemon)",!1).option("--db-path <path>","Path to the agent storage directory").option("--profile <profile>","Profile name for isolated config (env: VIBECONTROLS_PROFILE)").option("--host <host>","Host to bind to","0.0.0.0").option("--skip-plugin-install","Skip automatic installation of default plugins",!1).option("--skip-plugin <name>","Skip a specific default plugin (repeatable). Accepts the short pluginName or the full package name.",(q,$=[])=>[...$,q],[]).option("--no-install-deps","Skip auto-installing missing tools (installed by their plugins on start by default)").option("-y, --yes","Skip the first-run install consent prompt. Equivalent to VIBE_AUTO_ACCEPT=1; useful for CI / Docker / nohup contexts.",!1).option("--client-id <id>","Gateway OAuth client ID (env: VIBE_CLIENT_ID)").option("--client-secret <secret>","Gateway OAuth client secret (env: VIBE_CLIENT_SECRET)").option("--global-gateway-url <url>","Global gateway URL (env: VIBE_GLOBAL_GATEWAY_URL)").option("--workspace-gateway-url <url>","Workspace gateway URL (env: VIBE_WORKSPACE_GATEWAY_URL)").option("--workspace-id <id>","Workspace ID for auto-report (env: VIBE_WORKSPACE_ID)").option("--isolate <plugins>","Comma-separated list of plugin names to force into worker_threads isolation (Phase 4 hostile-plugin mode). Sets VIBE_ISOLATE_PLUGINS in the daemon env.").option("--profiles <names>","Comma-separated list of profiles to host in this daemon (multi-profile boot). When unset, the daemon hosts a single profile resolved via --profile / VIBECONTROLS_PROFILE / 'default'. Sets VIBECONTROLS_PROFILES in the daemon env so app boot can spin up additional ProfileContexts via the in-process registry.").option("--strict-key-fetch","Refuse to boot if any profile's encryption-key fetch fails. Default lenient: a failed profile is marked degraded and the daemon stays up. Sets VIBE_STRICT_KEY_FETCH=1 in the daemon env.",!1).option("--json","Emit JSON").option("--plain","Plain text output (no interactive TUI). Implied for non-TTY / CI.").option("--abilities <list>","Comma-separated ability keys to install non-interactively (e.g. session,ai,gitops). Storage/tunnel/backup are always included.").option("--providers <list>","Comma-separated extra provider plugins to install beyond each meta's default (e.g. session-wezterm,ai-claude). Accepts short names or @vibecontrols/... packages. Persisted; manage later with `vibe capability`.").option("--wait-ready [seconds]","Block until the agent is fully ready (or fails). Polls /health/ready and renders phase transitions live. Without a value, defaults to 60s. Exits non-zero if the agent ends up degraded or times out. Useful for scripts/CI.").option("--no-wait","Skip the phase tracker entirely after spawning the daemon. Restores the old fire-and-print behavior \u2014 for users who want the previous quick-return UX.").action(async function(q){let $={...Y.opts(),...q};try{let x=function(h){if(h==="default")return 3005;let d=2166136261;for(let g=0;g<h.length;g++)d=Math.imul(d^h.charCodeAt(g),16777619);return 3100+Math.abs(d)%300},Z=new p,X=q.profile||process.env.VIBECONTROLS_PROFILE||"default";if(process.env.VIBECONTROLS_PROFILE=X,typeof q.isolate==="string"&&q.isolate.length>0)process.env.VIBE_ISOLATE_PLUGINS=q.isolate;if(typeof q.profiles==="string"&&q.profiles.length>0){let h=q.profiles.split(",").map((d)=>d.trim()).filter(Boolean);if(h.length>0){if(process.env.VIBECONTROLS_PROFILES=h.join(","),process.env.VIBECONTROLS_PROFILE=h[0],h.length>1)j(`--profiles received ${h.length} entries; daemon boots with '${h[0]}'. Remaining (${h.slice(1).join(", ")}) will be attached via /api/profiles after listen.`)}}if(q.strictKeyFetch===!0)process.env.VIBE_STRICT_KEY_FETCH="1";a0();let H=q.dbPath||N$(),Q=Z$(),z=!o0(H)&&!o0(p2(Q,"agents.json")),V=f($),_=V!=="json"&&V!=="plain"&&t$()&&q.yes!==!0,O=r$(Q),F;if(typeof $.abilities==="string"&&$.abilities.trim()!=="")F=e0($.abilities);else if(O!==null)F=O;else if(_)F=await e$();else F=$0();let D=typeof $.providers==="string"&&$.providers.trim()!=="",R=D?s0($.providers):c$(Q);if(O===null){let h=r0({installDeps:q.installDeps===!0,skipPluginInstall:q.skipPluginInstall===!0,skipPlugins:Array.isArray(q.skipPlugin)?q.skipPlugin:[]},F);if(z&&h.plugins.length>0)J(),W(`Installing ${h.plugins.length} plugin(s) for the selected abilities.`),J();$1(Q,h,F,process.env.VIBE_AGENT_VERSION,R)}else if(D)D$(Q,{providers:R,agentVersion:process.env.VIBE_AGENT_VERSION});if((z||D)&&R.length>0&&q.skipPluginInstall!==!0){W(`Installing ${R.length} selected provider plugin(s)...`);try{let{PluginManager:h}=await import("./plugin-system-8hby8x1m.js"),d=new h;for(let g of R)try{await d.install(g),U(`Installed provider ${g}`)}catch(k){j(`Could not install provider ${g}: ${k instanceof Error?k.message:String(k)}`)}}catch(h){j(`Provider install skipped: ${h instanceof Error?h.message:String(h)}`)}J()}if(z){W("First run detected \u2014 running setup..."),J();let h=Array.isArray(q.skipPlugin)?q.skipPlugin:[],d=q.skipPluginInstall?[]:o$(process.platform,F).filter((s)=>!h.includes(s.packageName)&&!h.includes(s.pluginName)).map((s)=>s.packageName),g=t0(d),K$=a$(g).filter((s)=>!s.installed);if(K$.length>0)if(j(`Missing tools: ${K$.map((s)=>s.name).join(", ")}`),q.installDeps)W("Their plugins will install them automatically on startup.");else W("Auto-install skipped (`--no-install-deps`) \u2014 install them yourself or drop the flag.");else U("All plugin tools present.");J()}if(!q.skipPluginInstall){let h=Array.isArray(q.skipPlugin)?q.skipPlugin:[],d=new s$;await d.loadCorePlugins(),await d.loadAll();let g=await d.ensureDefaultPlugins((k)=>{if(k.startsWith("No "))j(k);else if(k.startsWith("Installed "))U(k);else if(k.startsWith("Failed "))j(k);else W(k)},h,F);if(g.length>0)U(`Auto-installed ${g.length} default plugin${g.length>1?"s":""}.`),J()}let G=q.profile||process.env.VIBECONTROLS_PROFILE||q.name||"default",M=q.port?parseInt(q.port,10):x(G);if(isNaN(M)||M<1||M>65535)L("Invalid port number. Must be between 1 and 65535.");let N=await p0(M);if(N!==M)j(`Port ${M} is in use. Auto-selecting port ${K.bold(String(N))} instead.`),M=N;let S=q.host,q$=`http://${S==="0.0.0.0"?"localhost":S}:${M}`,o=q.clientId||process.env.VIBE_CLIENT_ID,v=q.clientSecret||process.env.VIBE_CLIENT_SECRET,u=q.globalGatewayUrl||process.env.VIBE_GLOBAL_GATEWAY_URL,c=q.workspaceGatewayUrl||process.env.VIBE_WORKSPACE_GATEWAY_URL,O$=q.workspaceId||process.env.VIBE_WORKSPACE_ID;if(o&&!v)L("--client-secret is required when --client-id is provided.");if(v&&!o)L("--client-id is required when --client-secret is provided.");if(o&&v){if(!u&&!process.env.VIBE_GLOBAL_GATEWAY_URL)L("--global-gateway-url is required when providing client credentials (none set in env).");if(process.env.VIBE_CLIENT_ID=o,process.env.VIBE_CLIENT_SECRET=v,u)process.env.VIBE_GLOBAL_GATEWAY_URL=u;let{writeAgentConfig:h}=await import("./agent-config-4ppenhqp.js");if(h({clientId:o,clientSecret:v,workspaceId:O$,globalGatewayUrl:u,workspaceGatewayUrl:c}),c)process.env.VIBE_WORKSPACE_GATEWAY_URL=c;if(O$)process.env.VIBE_WORKSPACE_ID=O$;U("Gateway credentials staged in env. Agent will authenticate and persist them on startup."),J()}else if(c||O$||u){if(j("Workspace options provided without --client-id / --client-secret \u2014 they will be staged in env but unused until credentials are configured."),c)process.env.VIBE_WORKSPACE_GATEWAY_URL=c;if(O$)process.env.VIBE_WORKSPACE_ID=O$;if(u)process.env.VIBE_GLOBAL_GATEWAY_URL=u;J()}if(q.foreground){if(!$.json)T("Starting agent in foreground"),I("Name",q.name),I("Port",String(M)),I("Host",S),I("Database",H),J();let{bootstrapWorkspace:h}=await import("./bootstrap-workspace-qgs6d5f0.js");h();let{createApp:d}=await import("./app-9j2t5geq.js"),g=await d({port:M,host:S,dbPath:H});if(await g.start(),o&&v&&O$&&u&&c){let K$=await g.finalize({clientId:o,clientSecret:v,workspaceId:O$,globalGatewayUrl:u,workspaceGatewayUrl:c});if(!K$.ok)j(`Finalize failed \u2014 agent remains in awaiting-config state: ${K$.error}`)}if(B($,{ok:!0,name:q.name,port:M,host:S,pid:process.pid,url:q$}));else await u$(q$);let k=async()=>{await g.stop(),process.exit(0)};process.on("SIGTERM",k),process.on("SIGINT",k)}else{if(!$.json)T("Starting agent in daemon mode"),I("Name",q.name),I("Port",String(M)),I("Host",S),I("Database",H),J();if(q.installDeps===!1)process.env.VIBE_SKIP_PREREQ_INSTALL="1";await Z.startDaemon({port:M,name:q.name,daemon:!0,dbPath:H,host:S,profile:X});let d=(await Z.getStatus(q.name))?.port??M,k=`http://${S==="0.0.0.0"?"localhost":S}:${d}`,K$=q.waitReady,s=q.wait===!1,l0=K$!==void 0;if(s&&l0)j("--wait-ready is ignored because --no-wait was also passed.");let p$=!s&&l0,n0=!s&&(p$||!$.json),i0=(()=>{let C$=typeof K$==="string"?Number.parseInt(K$,10):NaN;if(Number.isInteger(C$)&&C$>0)return C$*1000;return p$?60000:25000})();if($.json){if(n0){let{trackAgentReady:C$}=await import("./agent-ready-tracker-kgs7td6t.js"),e=await C$(k,{timeoutMs:i0,verbose:!1});if(p$&&(e.outcome==="degraded"||e.outcome==="timeout"))process.exitCode=1;B($,{ok:e.outcome==="ready"||e.outcome==="awaiting-config",name:q.name,port:d,host:S,url:k,abilities:[...F],outcome:e.outcome,bootState:e.bootState,degradedReasons:e.degradedReasons,summary:e.summary})}else B($,{ok:!0,name:q.name,port:d,host:S,url:k});return}if(await u$(k),n0){let{trackAgentReady:C$}=await import("./agent-ready-tracker-kgs7td6t.js");J();let e=await C$(k,{timeoutMs:i0,verbose:!0});if(p$&&(e.outcome==="degraded"||e.outcome==="timeout"))process.exitCode=1}}}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}L(`Failed to start agent: ${X}`)}})}function q1(Y){Y.command("stop").description("Stop a running VibeControls agent instance").option("-n, --name <name>","Agent instance name","default").option("--all","Stop all running agent instances",!1).option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=new p;if(q.all){let X=await Z.listInstances();if(!X||X.length===0){if(B($,{ok:!0,stopped:[]}))return;T("Stopping all agent instances"),J(),W(`${E.info} No running agent instances found.`);return}let H=[];if(!$.json)T("Stopping all agent instances"),J();for(let Q of X)try{if(await Z.stop(Q.name),H.push(Q.name),!$.json)U(`${E.success} Stopped ${K.bold(Q.name)}`)}catch{if(!$.json)L(`Failed to stop ${K.bold(Q.name)}`)}if(B($,{ok:!0,stopped:H,total:X.length}))return;J(),U(`${E.success} Stopped ${H.length}/${X.length} instance(s).`)}else{if(await Z.stop(q.name),B($,{ok:!0,name:q.name}))return;T(`Stopping agent: ${q.name}`),J(),U(`${E.success} Agent ${K.bold(q.name)} stopped.`)}}catch(Z){if($.json){B($,{ok:!1,error:C(Z)});return}L(`Failed to stop agent: ${C(Z)}`)}})}function Z1(Y){Y.command("restart").description("Restart a running VibeControls agent instance").option("-n, --name <name>","Agent instance name","default").option("-p, --port <port>","Port to listen on").option("--db-path <path>","Path to the agent storage directory").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=new p;if(!$.json)T(`Restarting agent: ${q.name}`),J(),W(`${E.info} Stopping agent ${K.bold(q.name)}...`);let X=await Z.getStatus(q.name);try{if(await Z.stop(q.name),!$.json)U(`${E.success} Agent stopped.`)}catch{if(!$.json)W(`${E.info} Agent was not running.`)}let H=q.port??X?.port??3005,Q=typeof H==="number"?H:parseInt(H,10);if(isNaN(Q)||Q<1||Q>65535){if($.json){B($,{ok:!1,error:"Invalid port number"});return}L("Invalid port number. Must be between 1 and 65535.");return}let z={port:Q,name:q.name,daemon:!0,dbPath:q.dbPath??X?.config?.dbPath??N$(),host:X?.config?.host,profile:X?.config?.profile};if(!$.json)J(),W(`${E.info} Starting agent ${K.bold(q.name)}...`);await Z.startDaemon(z);let V=`http://localhost:${Q}`;if(B($,{ok:!0,name:q.name,port:Q,url:V}))return;J(),U(`${E.success} Agent ${K.bold(q.name)} restarted.`),J(),I("Port",String(Q)),I("Database",z.dbPath),J(),u$(V)}catch(Z){if($.json){B($,{ok:!1,error:C(Z)});return}L(`Failed to restart agent: ${C(Z)}`)}})}import{existsSync as o2,readFileSync as a2,unlinkSync as X1}from"fs";import{join as z1}from"path";function t2(Y){let q=z1(V$(),Y,"runtime.json");if(!o2(q))return null;try{let $=JSON.parse(a2(q,"utf8"));if(typeof $.pid!=="number")return null;return{...$,pid:$.pid,path:q}}catch{return null}}async function H1(Y){let q=t2(Y);if(!q)return null;if(!B$(q.pid)){try{X1(q.path)}catch{}return`agent pid=${q.pid} (${Y}) already gone (cleaned runtime.json).`}let $=l();if(!$.killProcessTree(q.pid,"SIGTERM"))return`failed to SIGTERM agent pid=${q.pid}.`;if(await new Promise((Z)=>setTimeout(Z,3000)),B$(q.pid))$.killProcessTree(q.pid,"SIGKILL");try{X1(q.path)}catch{}return`agent ${Y} pid=${q.pid}${q.port?` (port ${q.port})`:""} killed.`}async function s2(Y){let q=z1(V$(),Y),$=J$(q);if(!$)return null;if(!B$($.pid))return X$(q),`tunnel pid=${$.pid} already gone (cleaned state).`;let Z=l();if(!Z.killProcessTree($.pid,"SIGTERM"))return`failed to SIGTERM tunnel pid=${$.pid}.`;if(await new Promise((X)=>setTimeout(X,3000)),B$($.pid))Z.killProcessTree($.pid,"SIGKILL");return X$(q),`tunnel ${$.provider} pid=${$.pid} (${$.url??"no url"}) killed.`}function W1(Y){Y.command("kill").description("Force-kill an agent instance and its tunnel. Defaults to active profile.").option("-n, --name <name>","Agent instance name (alias of --profile, kept for back-compat)").option("--profile <name>","Kill a specific profile (overrides --name and VIBECONTROLS_PROFILE)").option("--all","Kill every agent instance and every profile's tunnel",!1).option("-y, --yes","Skip the confirmation prompt (for scripts/CI)",!1).option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q},Z=q.all?"ALL agent instances + every profile's tunnel":`agent '${$.profile??$.name??"active profile"}'`;if(!await q0($,`Force-kill ${Z}? This sends SIGKILL (no graceful shutdown).`)){W("Aborted.");return}let X=[];try{let H=new p;if(q.all){if(!$.json)T("Force killing all agent instances + tunnels"),J();let _=await H.listInstances()??[],O=0,F=new Set;for(let G of _)try{if(await H.kill(G.name),!$.json)U(`${E.success} agent ${K.bold(G.name)} (pid=${G.pid||"?"}) killed.`);X.push(G.name),O++,F.add(G.name)}catch{if(!$.json)j(`${E.warning} could not kill agent ${G.name}.`)}try{let G=await import("fs"),x=V$(),M=G.existsSync(x)?G.readdirSync(x):[];for(let N of M){if(F.has(N))continue;let S=await H1(N);if(S)U(`${E.success} ${S}`),O++}}catch(G){j(`${E.warning} runtime.json sweep failed: ${G instanceof Error?C(G):String(G)}`)}let D=Q1({allProfiles:!0}),R=0;for(let G of D){if(!G.alive){X$(G.profileDir);continue}let x=l();if(x.killProcessTree(G.pid,"SIGTERM"),await new Promise((M)=>setTimeout(M,3000)),B$(G.pid))x.killProcessTree(G.pid,"SIGKILL");X$(G.profileDir),U(`${E.success} tunnel ${G.provider} pid=${G.pid} (${G.url??"no url"}, ${G.profileDir.split("/").pop()}) killed.`),R++}if(B($,{ok:!0,killed:X,tunnels:R}))return;J(),U(`${E.success} killed ${O} agent(s) and ${R} tunnel(s).`);return}let Q=q.profile||q.name||Y0();if(!$.json)T(`Force killing profile: ${Q}`),J();let z=await H.getStatus(Q);if(z){if(await H.kill(Q),X.push(Q),!$.json)U(`${E.success} agent ${K.bold(Q)} pid=${z.pid||"?"} killed.`)}else{let _=await H1(Q);if(_){if(X.push(Q),!$.json)U(`${E.success} ${_}`)}else if(!$.json)W(`${E.info} no running agent service for profile ${Q}.`)}let V=await s2(Q);if(V){if(!$.json)U(`${E.success} ${V}`)}else if(!$.json)W(`${E.info} no tunnel recorded for profile ${Q}.`);B($,{ok:!0,killed:X})}catch(H){if($.json){B($,{ok:!1,error:C(H)});return}L(`Failed to kill: ${C(H)}`)}})}function K1(Y){Y.command("list").alias("ls").description("List all VibeControls agent instances").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function(q){try{let $={...Y.opts(),...q},Z=new p;await P({mode:f($),fetchData:()=>Z.listInstances(),plain:(X)=>{if(T("Agent Instances"),J(),!X||X.length===0){W(`${E.info} No agent instances found.`),W(`Run ${K.bold("vibe start")} to start an agent.`);return}let H=X.map((V)=>({Name:V.name,Status:x$(V.status),PID:V.pid||"-",Port:V.port||"-",Host:V.config?.host||"-",Database:V.config?.dbPath||"-",Started:V.startTime?G$(V.startTime):"-"}));n(H),J();let Q=X.filter((V)=>V.status==="running").length,z=X.length-Q;W(`${E.info} ${X.length} instance(s): ${K.green(String(Q))} running, ${K.dim(String(z))} stopped`)},interactive:async(X)=>{if(!X||X.length===0){T("Agent Instances"),J(),W(`${E.info} No agent instances found.`),W(`Run ${K.bold("vibe start")} to start an agent.`);return}let H=X.map((Q)=>{let z=[`${K.bold(Q.name)} ${x$(Q.status)}`,"",` PID: ${Q.pid??"-"}`,` Port: ${Q.port??"-"}`,` Host: ${Q.config?.host??"-"}`,` Database: ${Q.config?.dbPath??"-"}`,` Started: ${Q.startTime?G$(Q.startTime):"-"}`];return{id:Q.name,label:Q.name,hint:Q.status==="running"?"running":"stopped",detail:z.join(`
3
+ `)}});await r({title:`vibe list \u2014 ${X.length} instance(s)`,rows:H,footer:"\u2191/\u2193 navigate \xB7 q to quit"})},json:(X)=>X.map((H)=>({name:H.name,status:H.status,pid:H.pid??null,port:H.port??null,host:H.config?.host??null,database:H.config?.dbPath??null,startTime:H.startTime??null}))})}catch($){L(`Failed to list instances: ${$.message}`)}})}var V1=5000;function L1(Y){Y.command("logs").description("View logs for a VibeControls agent instance").option("-n, --name <name>","Agent instance name","default").option("-f, --follow","Follow log output",!1).option("--tail <lines>","Number of lines to show from the end","100").option("--json","Emit JSON (one object per line, banners suppressed)").option("--plain","Force plain text output").action(async function(q){try{let $={...Y.opts(),...q},Z=new p,X=parseInt($.tail??"100",10);if(isNaN(X)||X<1||X>V1){L(`Invalid tail value. Must be between 1 and ${V1}.`);return}let H=$.name??"default";if(!await Z.getStatus(H)){L(`Agent instance ${K.bold(H)} not found.`);return}if(!$.json){if($.follow)T(`Following logs: ${H}`),W(`${E.info} Press Ctrl+C to stop following.`);else T(`Logs: ${H}`);J()}await Z.showLogs(H,{follow:!!$.follow,tail:X})}catch($){L(`Failed to get logs: ${C($)}`)}})}function J1(Y){Y.command("setup").description("Install system dependencies and (optionally) write gateway auth config").option("--check","Only check dependencies without installing",!1).option("--client-id <id>","OAuth app client ID (for backend authentication)").option("--client-secret <secret>","OAuth app client secret").option("--workspace-id <id>","Workspace UUID this agent belongs to").option("--global-gateway-url <url>","Global public gateway URL (default: http://localhost:4000/global/graphql)").option("--workspace-gateway-url <url>","Workspace gateway URL (default: http://localhost:4001/workspaces/graphql)").option("--storage-adapter <name>","Named storage adapter (default: skalex, or custom:<path>)").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q},Z=[];try{if(!$.json)T("VibeControls Agent Setup");let X={};if(q.clientId)X.clientId=q.clientId;if(q.clientSecret)X.clientSecret=q.clientSecret;if(q.workspaceId)X.workspaceId=q.workspaceId;if(q.globalGatewayUrl)X.globalGatewayUrl=O0(q.globalGatewayUrl,"globalGatewayUrl");if(q.workspaceGatewayUrl)X.workspaceGatewayUrl=O0(q.workspaceGatewayUrl,"workspaceGatewayUrl");if(q.storageAdapter)X.storageAdapter=q.storageAdapter;if(Object.keys(X).length>0){let O=U$(X);if(Z.push(...Object.keys(X)),!$.json){U(`Agent config written to ${B0()}`),I("clientId",O.clientId?K.dim("(set)"):K.dim("(unset)")),I("clientSecret",O.clientSecret?K.dim("(set)"):K.dim("(unset)")),I("workspaceId",O.workspaceId??K.dim("(unset)"));let F=O1();if(I("globalGatewayUrl",O.globalGatewayUrl??F.globalGatewayUrl),I("workspaceGatewayUrl",O.workspaceGatewayUrl??F.workspaceGatewayUrl),O.storageAdapter)I("storageAdapter",O.storageAdapter);J()}}else{let O=Y$();if((O.clientId||O.clientSecret||O.workspaceId)&&!$.json)W(`Using existing agent config at ${B0()} (pass --client-id/--client-secret/--workspace-id to update).`),J()}if(!$.json)W("Checking dependencies..."),J();let H=a$(),Q=[],z=[];for(let O of H){if(O.installed)z.push(O.name);if(!$.json){let F=O.installed?E.success:E.error,D=O.version?K.dim(` (${O.version})`):"",R=O.required?"":K.dim(" [optional]");I(`${F} ${O.name}`,`${O.installed?K.green("installed"):K.red("missing")}${D}${R}`)}if(!O.installed)Q.push(O.name)}if(!$.json)J();if(Q.length===0){if(B($,{ok:!0,installed:z,configured:Z}))return;U("All dependencies are installed.");return}if(q.check){if($.json){B($,{ok:!1,installed:z,missing:Q,configured:Z});return}j(`Missing: ${Q.join(", ")}`),W(`Run ${K.bold("vibe setup")} to install them.`),process.exit(1)}if(!$.json)W(`Installing missing dependencies: ${Q.join(", ")}...`),J();let V=await B1(Q),_=Q.filter((O)=>!V.failed.includes(O));if(V.failed.length>0){if($.json){B($,{ok:!1,installed:[...z,..._],failed:V.failed,configured:Z});return}j(`${V.failed.length} tool(s) failed: ${V.failed.join(", ")}`),W("You may need to install manually or use sudo."),process.exit(1)}else{if(B($,{ok:!0,installed:[...z,..._],configured:Z}))return;U("All dependencies installed successfully.")}}catch(X){let H=X instanceof Error?C(X):String(X);if($.json){B($,{ok:!1,error:H});return}L(`Setup failed: ${H}`)}})}function r2(Y){let q=l();return q.which(Y)??`${Y}${q.executableSuffix}`}function C1(Y){Y.command("update").description("Check for and install VibeControls agent updates").option("--check","Only check for updates without installing",!1).option("--allow-incompatible","Override engines.bun compatibility check (use with care)",!1).option("--no-restart","Skip the post-install idle-aware restart of any running agent").option("-n, --name <name>","Agent profile name to restart after update","default").option("--version-target <version>","Install a specific version instead of the latest (e.g. 2026.601.21)").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{if(!$.json)T("VibeControls Agent Update"),J(),W(`${E.info} Checking for updates...`),J();let Z=await I1();if(Z.error&&!Z.latest){if(B($,{ok:!1,current:Z.current,error:Z.error}))return;L(Z.error);return}if(!$.json)I("Package",K.bold(Z.name)),I("Registry",K.bold(Z.registry)),I("Current version",K.bold(Z.current)),I("Latest version",K.bold(Z.latest??"unknown")),J();if(q.check){if(B($,{ok:!0,current:Z.current,latest:Z.latest,upToDate:!Z.hasUpdate}))return;if(!Z.hasUpdate)U(`${E.success} You are running the latest version.`);else j(`${E.warning} A new version is available: ${K.green(Z.latest??"")}`),W(`${E.info} Run ${K.bold("vibe update")} to install the update.`);return}let X=q.versionTarget;if(!X&&!Z.hasUpdate){if(B($,{ok:!0,current:Z.current,latest:Z.latest,upToDate:!0}))return;U(`${E.success} You are running the latest version.`);return}if(!$.json)W(`${E.info} Updating to ${K.bold(X??Z.latest??"latest")}...`),J();let H=await _1({targetVersion:X,allowIncompatible:!!q.allowIncompatible,restart:q.restart!==!1,name:q.name,onLog:$.json?void 0:(Q)=>W(`${E.info} ${Q}`)});if(!H.ok){if(B($,{ok:!1,current:H.current,previous:H.previous,latest:H.latest,rolledBack:H.rolledBack,error:H.error}))return;L(H.error??"Update failed.");return}if(!$.json)switch(H.restart){case"restarted":U(`${E.success} Restarted agent ${K.bold(q.name)} on the new version.`);break;case"not-running":W(`${E.info} No running agent for profile ${K.bold(q.name)}; nothing to restart.`);break;case"still-busy":j(`${E.warning} Agent still serving requests \u2014 run ${K.bold("vibe restart")} when it's quiet.`);break;case"error":j(`${E.warning} Auto-restart failed: ${H.restartError}. Run ${K.bold("vibe restart")} manually.`);break}if(B($,{ok:!0,current:H.current,previous:H.previous,latest:H.latest,updated:H.updated,restart:H.restart,...H.restartError?{restartError:H.restartError}:{}}))return;if(J(),H.updated)U(`${E.success} Updated to ${K.bold(H.current)} (smoke: ${H.smoke?.step??"ok"}).`);else U(`${E.success} You are running the latest version.`);if(q.restart===!1)W(`${E.info} --no-restart set \u2014 restart running agents manually for the update to take effect.`)}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}L(`Update failed: ${X}`)}}),Y.command("rollback").description("Roll the global agent install back to a specific version").argument("<version>","Target CalVer version (e.g. 2026.428.3)").action(async(q)=>{try{T("VibeControls Agent Rollback");let $=await U1();if(I("Package",K.bold($.name)),I("Current version",K.bold($.version)),I("Target version",K.bold(q)),J(),W(`${E.info} Rolling back\u2026`),Bun.spawnSync([r2("npm"),"install","-g",`${$.name}@${q}`,`--registry=${$.registry}`],{stdout:"inherit",stderr:"inherit"}).exitCode!==0){L("Rollback failed.");return}U(`${E.success} Rolled back to ${K.bold(q)}.`)}catch($){L(`Rollback failed: ${$ instanceof Error?C($):String($)}`)}})}import{existsSync as F$,mkdirSync as e2,writeFileSync as I0,unlinkSync as $6,readFileSync as J0}from"fs";import{join as L$}from"path";import{homedir as M$}from"os";var Y6=/^[A-Za-z0-9][A-Za-z0-9:_-]{0,63}$/,q6=/^--[A-Za-z0-9][A-Za-z0-9-]{0,63}$/;function R1(Y){return Y6.test(Y)?Y:null}function j1(Y){return Y.filter((q)=>R1(q))}function Z6(Y){return Y.filter((q)=>q6.test(q))}function w$(Y){return Y.commands.flatMap((q)=>{let $=R1(q.name());if(!$)return[];return[{name:$,description:q.description()||"",options:q.options.map((Z)=>({flags:Z.flags,description:Z.description||""})),subcommands:w$(q)}]})}function X6(Y){return j1(Y.map((q)=>q.name))}function H6(Y,q){let $=Y.find((X)=>X.name===q);if(!$)return[];let Z=[];for(let X of $.options){let H=X.flags.match(/--([\w-]+)/);if(H)Z.push(`--${H[1]}`)}return Z6(Z)}function E1(Y){let q=X6(Y),Z=Y.filter((H)=>H.subcommands.length>0).map((H)=>({name:H.name,subs:j1(H.subcommands.map((Q)=>Q.name))})).map((H)=>` ${H.name})
4
4
  COMPREPLY=($(compgen -W "${H.subs.join(" ")}" -- "\${cur}"))
5
5
  return 0
6
6
  ;;`).join(`
@@ -84,7 +84,7 @@ ${Z0}`;return T1(Z,d$,X),{shell:$,path:Z}}case"zsh":{let Z=L$(M$(),".zshrc"),X=`
84
84
  eval "$(vibe completion zsh)"
85
85
  ${Z0}`;return T1(Z,d$,X),{shell:$,path:Z}}case"fish":{let Z=L$(process.env.XDG_CONFIG_HOME||L$(M$(),".config"),"fish","completions");if(!F$(Z))e2(Z,{recursive:!0});let X=L$(Z,"vibe.fish");return I0(X,_0(Y),"utf8"),{shell:$,path:X}}}}function M1(Y){let q=Y||D1();switch(q){case"bash":{let $=w1();return U0($),{shell:q,path:$}}case"zsh":{let $=L$(M$(),".zshrc");return U0($),{shell:q,path:$}}case"fish":{let $=L$(process.env.XDG_CONFIG_HOME||L$(M$(),".config"),"fish","completions","vibe.fish");if(F$($))$6($);return{shell:q,path:$}}}}function w1(){let Y=L$(M$(),".bashrc");if(F$(Y))return Y;let q=L$(M$(),".bash_profile");if(F$(q))return q;return Y}function T1(Y,q,$){let Z="";if(F$(Y))Z=J0(Y,"utf8");if(Z.includes(q))U0(Y),Z=F$(Y)?J0(Y,"utf8"):"";I0(Y,Z+`
86
86
  `+$+`
87
- `,"utf8")}function U0(Y){if(!F$(Y))return;let q=J0(Y,"utf8"),$=q.indexOf(d$),Z=q.indexOf(Z0);if($===-1||Z===-1)return;I0(Y,q.substring(0,$)+q.substring(Z+Z0.length),"utf8")}function A1(Y){let q=Y.command("completion").description("Generate shell completion scripts (bash, zsh, fish)");q.command("bash").description("Print Bash completion script").action(()=>{let $=w$(Y);process.stdout.write(E1($))}),q.command("zsh").description("Print Zsh completion script").action(()=>{let $=w$(Y);process.stdout.write(N1($))}),q.command("fish").description("Print Fish completion script").action(()=>{let $=w$(Y);process.stdout.write(_0($))}),q.command("install").description("Auto-install completions for your current shell").option("--shell <shell>","Force a specific shell (bash, zsh, fish). Auto-detects if omitted.").action(($)=>{try{let Z=w$(Y),X=x1(Z,$.shell);U(`Completions installed for ${X.shell}`),W(`Written to: ${X.path}`),W("Restart your shell or run:"),console.log(` source ${X.path}`),console.log()}catch(Z){V(`Failed to install completions: ${Z instanceof Error?C(Z):Z}`)}}),q.command("uninstall").description("Remove previously installed completions").option("--shell <shell>","Force a specific shell (bash, zsh, fish)").action(($)=>{try{let Z=M1($.shell);U(`Completions removed for ${Z.shell}`),W(`Cleaned: ${Z.path}`),console.log()}catch(Z){V(`Failed to uninstall completions: ${Z instanceof Error?C(Z):Z}`)}})}import{existsSync as l$,mkdirSync as A$,writeFileSync as F0,unlinkSync as T0}from"fs";import{join as H$}from"path";import{homedir as S$,platform as G0}from"os";import{isAbsolute as Q6,resolve as z6}from"path";function R0(){return Q$()}function g$(){return H$(R0(),"logs")}function j0(){if(process.execPath&&process.execPath.includes("bun"))return process.execPath;let Y=l().which("bun");if(Y)return Y;throw Error("Could not find bun binary. Ensure bun is installed and in PATH.")}function E0(){return import.meta.dir.endsWith("/dist")||import.meta.dir.includes("/dist/")?H$(import.meta.dir,"index.js"):H$(import.meta.dir,"..","..","index.ts")}function X0(Y,q){if(/[\0\r\n]/.test(Y))throw Error(`${q} contains invalid control characters`)}function m$(Y){if(!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(Y))throw Error("Agent name must use 1-64 characters: letters, numbers, dot, underscore, or dash.");return Y}function W6(Y){let q=parseInt(Y,10);if(!Number.isInteger(q)||q<1||q>65535)throw Error("Port must be an integer between 1 and 65535");return q}function I$(Y){return X0(Y,"systemd value"),`"${Y.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function k(Y){let q=String(Y);return X0(q,"plist value"),q.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function N0(Y){let q=H$(S$(),".config","systemd","user");return A$(q,{recursive:!0}),H$(q,`vibecontrols-agent-${Y}.service`)}function K6(Y){return`[Unit]
87
+ `,"utf8")}function U0(Y){if(!F$(Y))return;let q=J0(Y,"utf8"),$=q.indexOf(d$),Z=q.indexOf(Z0);if($===-1||Z===-1)return;I0(Y,q.substring(0,$)+q.substring(Z+Z0.length),"utf8")}function A1(Y){let q=Y.command("completion").description("Generate shell completion scripts (bash, zsh, fish)");q.command("bash").description("Print Bash completion script").action(()=>{let $=w$(Y);process.stdout.write(E1($))}),q.command("zsh").description("Print Zsh completion script").action(()=>{let $=w$(Y);process.stdout.write(N1($))}),q.command("fish").description("Print Fish completion script").action(()=>{let $=w$(Y);process.stdout.write(_0($))}),q.command("install").description("Auto-install completions for your current shell").option("--shell <shell>","Force a specific shell (bash, zsh, fish). Auto-detects if omitted.").action(($)=>{try{let Z=w$(Y),X=x1(Z,$.shell);U(`Completions installed for ${X.shell}`),W(`Written to: ${X.path}`),W("Restart your shell or run:"),console.log(` source ${X.path}`),console.log()}catch(Z){L(`Failed to install completions: ${Z instanceof Error?C(Z):Z}`)}}),q.command("uninstall").description("Remove previously installed completions").option("--shell <shell>","Force a specific shell (bash, zsh, fish)").action(($)=>{try{let Z=M1($.shell);U(`Completions removed for ${Z.shell}`),W(`Cleaned: ${Z.path}`),console.log()}catch(Z){L(`Failed to uninstall completions: ${Z instanceof Error?C(Z):Z}`)}})}import{existsSync as l$,mkdirSync as A$,writeFileSync as F0,unlinkSync as T0}from"fs";import{join as H$}from"path";import{homedir as S$,platform as G0}from"os";import{isAbsolute as Q6,resolve as z6}from"path";function R0(){return Q$()}function g$(){return H$(R0(),"logs")}function j0(){if(process.execPath&&process.execPath.includes("bun"))return process.execPath;let Y=l().which("bun");if(Y)return Y;throw Error("Could not find bun binary. Ensure bun is installed and in PATH.")}function E0(){return import.meta.dir.endsWith("/dist")||import.meta.dir.includes("/dist/")?H$(import.meta.dir,"index.js"):H$(import.meta.dir,"..","..","index.ts")}function X0(Y,q){if(/[\0\r\n]/.test(Y))throw Error(`${q} contains invalid control characters`)}function m$(Y){if(!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(Y))throw Error("Agent name must use 1-64 characters: letters, numbers, dot, underscore, or dash.");return Y}function W6(Y){let q=parseInt(Y,10);if(!Number.isInteger(q)||q<1||q>65535)throw Error("Port must be an integer between 1 and 65535");return q}function I$(Y){return X0(Y,"systemd value"),`"${Y.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function b(Y){let q=String(Y);return X0(q,"plist value"),q.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function N0(Y){let q=H$(S$(),".config","systemd","user");return A$(q,{recursive:!0}),H$(q,`vibecontrols-agent-${Y}.service`)}function K6(Y){return`[Unit]
88
88
  Description=VibeControls Agent (${Y.name})
89
89
  After=network.target
90
90
 
@@ -105,35 +105,35 @@ StandardError=append:${Y.logFile}
105
105
 
106
106
  [Install]
107
107
  WantedBy=default.target
108
- `}async function V6(Y,q,$){m$(Y),X0($,"dbPath");let Z=j0(),X=E0(),H=H$(g$(),`${Y}.log`),Q=N0(Y),z=`vibecontrols-agent-${Y}.service`;A$(g$(),{recursive:!0});let L=K6({name:Y,port:q,dbPath:$,bunPath:Z,entryPoint:X,logFile:H});F0(Q,L),W(`Wrote systemd unit: ${Q}`);let I=[["systemctl","--user","daemon-reload"],["systemctl","--user","enable",z],["systemctl","--user","start",z]];for(let G of I){let x=Bun.spawnSync(G);if(x.exitCode!==0){let F=x.stderr.toString().trim();j(`Command failed: ${G.join(" ")}${F?` \u2014 ${F}`:""}`)}}if(Bun.spawnSync(["loginctl","enable-linger",process.env.USER||""]).exitCode===0)W("Enabled user linger (service survives logout)");U(`Autostart installed for agent '${Y}' on port ${q}`),_("Service",z),_("Unit file",Q),_("Log file",H),J(),W(`Check status: systemctl --user status ${z}`)}async function L6(Y){let q=`vibecontrols-agent-${Y}.service`,$=N0(Y),Z=[["systemctl","--user","stop",q],["systemctl","--user","disable",q]];for(let X of Z)Bun.spawnSync(X);if(l$($))T0($),W(`Removed unit file: ${$}`);Bun.spawnSync(["systemctl","--user","daemon-reload"]),U(`Autostart removed for agent '${Y}'`)}async function O6(Y){let q=`vibecontrols-agent-${Y}.service`,$=N0(Y);if(!l$($)){W(`Autostart is NOT configured for agent '${Y}'`),_("Expected unit",$);return}T(`Autostart Status \u2014 ${Y}`),_("Unit file",$),_("Service",q),J();let X=Bun.spawnSync(["systemctl","--user","status",q]).stdout.toString().trim();if(X)console.log(X);else W("Service status unavailable")}function D0(Y){let q=H$(S$(),"Library","LaunchAgents");return A$(q,{recursive:!0}),H$(q,`com.boff.vibecontrols.agent.${Y}.plist`)}function B6(Y){return`<?xml version="1.0" encoding="UTF-8"?>
108
+ `}async function V6(Y,q,$){m$(Y),X0($,"dbPath");let Z=j0(),X=E0(),H=H$(g$(),`${Y}.log`),Q=N0(Y),z=`vibecontrols-agent-${Y}.service`;A$(g$(),{recursive:!0});let V=K6({name:Y,port:q,dbPath:$,bunPath:Z,entryPoint:X,logFile:H});F0(Q,V),W(`Wrote systemd unit: ${Q}`);let _=[["systemctl","--user","daemon-reload"],["systemctl","--user","enable",z],["systemctl","--user","start",z]];for(let F of _){let D=Bun.spawnSync(F);if(D.exitCode!==0){let R=D.stderr.toString().trim();j(`Command failed: ${F.join(" ")}${R?` \u2014 ${R}`:""}`)}}if(Bun.spawnSync(["loginctl","enable-linger",process.env.USER||""]).exitCode===0)W("Enabled user linger (service survives logout)");U(`Autostart installed for agent '${Y}' on port ${q}`),I("Service",z),I("Unit file",Q),I("Log file",H),J(),W(`Check status: systemctl --user status ${z}`)}async function L6(Y){let q=`vibecontrols-agent-${Y}.service`,$=N0(Y),Z=[["systemctl","--user","stop",q],["systemctl","--user","disable",q]];for(let X of Z)Bun.spawnSync(X);if(l$($))T0($),W(`Removed unit file: ${$}`);Bun.spawnSync(["systemctl","--user","daemon-reload"]),U(`Autostart removed for agent '${Y}'`)}async function O6(Y){let q=`vibecontrols-agent-${Y}.service`,$=N0(Y);if(!l$($)){W(`Autostart is NOT configured for agent '${Y}'`),I("Expected unit",$);return}T(`Autostart Status \u2014 ${Y}`),I("Unit file",$),I("Service",q),J();let X=Bun.spawnSync(["systemctl","--user","status",q]).stdout.toString().trim();if(X)console.log(X);else W("Service status unavailable")}function D0(Y){let q=H$(S$(),"Library","LaunchAgents");return A$(q,{recursive:!0}),H$(q,`com.boff.vibecontrols.agent.${Y}.plist`)}function B6(Y){return`<?xml version="1.0" encoding="UTF-8"?>
109
109
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
110
110
  <plist version="1.0">
111
111
  <dict>
112
112
  <key>Label</key>
113
- <string>com.boff.vibecontrols.agent.${k(Y.name)}</string>
113
+ <string>com.boff.vibecontrols.agent.${b(Y.name)}</string>
114
114
  <key>ProgramArguments</key>
115
115
  <array>
116
- <string>${k(Y.bunPath)}</string>
116
+ <string>${b(Y.bunPath)}</string>
117
117
  <string>run</string>
118
- <string>${k(Y.entryPoint)}</string>
118
+ <string>${b(Y.entryPoint)}</string>
119
119
  </array>
120
120
  <key>EnvironmentVariables</key>
121
121
  <dict>
122
122
  <key>PORT</key>
123
- <string>${k(Y.port)}</string>
123
+ <string>${b(Y.port)}</string>
124
124
  <key>DB_PATH</key>
125
- <string>${k(Y.dbPath)}</string>
125
+ <string>${b(Y.dbPath)}</string>
126
126
  <key>NODE_ENV</key>
127
127
  <string>production</string>
128
128
  <key>AGENT_LOG_FILE</key>
129
- <string>${k(Y.logFile)}</string>
129
+ <string>${b(Y.logFile)}</string>
130
130
  <key>HOME</key>
131
- <string>${k(S$())}</string>
131
+ <string>${b(S$())}</string>
132
132
  <key>PATH</key>
133
- <string>${k(process.env.PATH??"")}</string>
133
+ <string>${b(process.env.PATH??"")}</string>
134
134
  </dict>
135
135
  <key>WorkingDirectory</key>
136
- <string>${k(S$())}</string>
136
+ <string>${b(S$())}</string>
137
137
  <key>RunAtLoad</key>
138
138
  <true/>
139
139
  <key>KeepAlive</key>
@@ -142,29 +142,29 @@ WantedBy=default.target
142
142
  <false/>
143
143
  </dict>
144
144
  <key>StandardOutPath</key>
145
- <string>${k(Y.logFile)}</string>
145
+ <string>${b(Y.logFile)}</string>
146
146
  <key>StandardErrorPath</key>
147
- <string>${k(Y.logFile)}</string>
147
+ <string>${b(Y.logFile)}</string>
148
148
  <key>ProcessType</key>
149
149
  <string>Background</string>
150
150
  </dict>
151
151
  </plist>
152
- `}async function J6(Y,q,$){m$(Y),X0($,"dbPath");let Z=j0(),X=E0(),H=H$(g$(),`${Y}.log`),Q=D0(Y);A$(g$(),{recursive:!0});let z=B6({name:Y,port:q,dbPath:$,bunPath:Z,entryPoint:X,logFile:H});F0(Q,z),W(`Wrote launchd plist: ${Q}`);let L=Bun.spawnSync(["launchctl","load",Q]);if(L.exitCode!==0){let I=L.stderr.toString().trim();j(`launchctl load failed: ${I}`),W("Trying bootstrap method...");let O=Bun.spawnSync(["id","-u"]).stdout.toString().trim();Bun.spawnSync(["launchctl","bootstrap",`gui/${O}`,Q])}U(`Autostart installed for agent '${Y}' on port ${q}`),_("Plist",Q),_("Log file",H)}async function U6(Y){let q=D0(Y),$=`com.boff.vibecontrols.agent.${Y}`;Bun.spawnSync(["launchctl","unload",q]);let Z=Bun.spawnSync(["id","-u"]).stdout.toString().trim();if(Bun.spawnSync(["launchctl","bootout",`gui/${Z}/${$}`]),l$(q))T0(q),W(`Removed plist: ${q}`);U(`Autostart removed for agent '${Y}'`)}async function I6(Y){let q=D0(Y),$=`com.boff.vibecontrols.agent.${Y}`;if(!l$(q)){W(`Autostart is NOT configured for agent '${Y}'`),_("Expected plist",q);return}T(`Autostart Status \u2014 ${Y}`),_("Plist",q),_("Label",$),J();let H=Bun.spawnSync(["launchctl","list"]).stdout.toString().split(`
152
+ `}async function J6(Y,q,$){m$(Y),X0($,"dbPath");let Z=j0(),X=E0(),H=H$(g$(),`${Y}.log`),Q=D0(Y);A$(g$(),{recursive:!0});let z=B6({name:Y,port:q,dbPath:$,bunPath:Z,entryPoint:X,logFile:H});F0(Q,z),W(`Wrote launchd plist: ${Q}`);let V=Bun.spawnSync(["launchctl","load",Q]);if(V.exitCode!==0){let _=V.stderr.toString().trim();j(`launchctl load failed: ${_}`),W("Trying bootstrap method...");let O=Bun.spawnSync(["id","-u"]).stdout.toString().trim();Bun.spawnSync(["launchctl","bootstrap",`gui/${O}`,Q])}U(`Autostart installed for agent '${Y}' on port ${q}`),I("Plist",Q),I("Log file",H)}async function U6(Y){let q=D0(Y),$=`com.boff.vibecontrols.agent.${Y}`;Bun.spawnSync(["launchctl","unload",q]);let Z=Bun.spawnSync(["id","-u"]).stdout.toString().trim();if(Bun.spawnSync(["launchctl","bootout",`gui/${Z}/${$}`]),l$(q))T0(q),W(`Removed plist: ${q}`);U(`Autostart removed for agent '${Y}'`)}async function I6(Y){let q=D0(Y),$=`com.boff.vibecontrols.agent.${Y}`;if(!l$(q)){W(`Autostart is NOT configured for agent '${Y}'`),I("Expected plist",q);return}T(`Autostart Status \u2014 ${Y}`),I("Plist",q),I("Label",$),J();let H=Bun.spawnSync(["launchctl","list"]).stdout.toString().split(`
153
153
  `).filter((Q)=>Q.includes("vibecontrols"));if(H.length>0)console.log(H.join(`
154
- `));else W("Service not currently loaded")}function x0(Y){return`VibeControlsAgent_${Y}`}function S1(Y){return H$(R0(),`autostart-${Y}.xml`)}function _6(Y){let q=[`<Variable><Name>VIBECONTROLS_PROFILE</Name><Value>${k(Y.name)}</Value></Variable>`,`<Variable><Name>PORT</Name><Value>${k(Y.port)}</Value></Variable>`,`<Variable><Name>VIBECONTROLS_HOME</Name><Value>${k(Y.configDir)}</Value></Variable>`];if(Y.dbPath)q.push(`<Variable><Name>DB_PATH</Name><Value>${k(Y.dbPath)}</Value></Variable>`);let $=process.env.USERNAME??process.env.USER??"User";return`<?xml version="1.0" encoding="UTF-16"?>
154
+ `));else W("Service not currently loaded")}function x0(Y){return`VibeControlsAgent_${Y}`}function S1(Y){return H$(R0(),`autostart-${Y}.xml`)}function _6(Y){let q=[`<Variable><Name>VIBECONTROLS_PROFILE</Name><Value>${b(Y.name)}</Value></Variable>`,`<Variable><Name>PORT</Name><Value>${b(Y.port)}</Value></Variable>`,`<Variable><Name>VIBECONTROLS_HOME</Name><Value>${b(Y.configDir)}</Value></Variable>`];if(Y.dbPath)q.push(`<Variable><Name>DB_PATH</Name><Value>${b(Y.dbPath)}</Value></Variable>`);let $=process.env.USERNAME??process.env.USER??"User";return`<?xml version="1.0" encoding="UTF-16"?>
155
155
  <Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
156
156
  <RegistrationInfo>
157
- <Description>VibeControls Agent (${k(Y.name)}) \u2014 auto-start on logon, restart on crash</Description>
157
+ <Description>VibeControls Agent (${b(Y.name)}) \u2014 auto-start on logon, restart on crash</Description>
158
158
  </RegistrationInfo>
159
159
  <Triggers>
160
160
  <LogonTrigger>
161
161
  <Enabled>true</Enabled>
162
- <UserId>${k($)}</UserId>
162
+ <UserId>${b($)}</UserId>
163
163
  </LogonTrigger>
164
164
  </Triggers>
165
165
  <Principals>
166
166
  <Principal id="Author">
167
- <UserId>${k($)}</UserId>
167
+ <UserId>${b($)}</UserId>
168
168
  <LogonType>InteractiveToken</LogonType>
169
169
  <RunLevel>LeastPrivilege</RunLevel>
170
170
  </Principal>
@@ -194,38 +194,38 @@ WantedBy=default.target
194
194
  </Settings>
195
195
  <Actions Context="Author">
196
196
  <Exec>
197
- <Command>${k(Y.bunPath)}</Command>
198
- <Arguments>${k(Y.entryPoint)} start --foreground --port ${k(Y.port)} --name ${k(Y.name)}</Arguments>
199
- <WorkingDirectory>${k(Y.configDir)}</WorkingDirectory>
197
+ <Command>${b(Y.bunPath)}</Command>
198
+ <Arguments>${b(Y.entryPoint)} start --foreground --port ${b(Y.port)} --name ${b(Y.name)}</Arguments>
199
+ <WorkingDirectory>${b(Y.configDir)}</WorkingDirectory>
200
200
  </Exec>
201
201
  </Actions>
202
- </Task>`}async function C6(Y,q,$){let Z=x0(Y),X=S1(Y),H=R0(),Q=g$();A$(H,{recursive:!0}),A$(Q,{recursive:!0});let z=j0(),L=E0(),I=_6({name:Y,port:q,dbPath:$,bunPath:z,entryPoint:L,configDir:H,logsDir:Q}),O=Buffer.concat([Buffer.from([255,254]),Buffer.from(I,"utf16le")]);if(F0(X,O),_("Task XML",X),Bun.spawnSync(["schtasks","/Create","/TN",Z,"/XML",X,"/F"],{stdout:"inherit",stderr:"inherit"}).exitCode!==0)throw Error("schtasks /Create failed. Run from an elevated shell if your user lacks scheduler permission.");J(),U(`Autostart installed for agent '${Y}' (Task: ${Z})`),W("To start now without rebooting:"),W(` schtasks /Run /TN ${Z}`)}async function G6(Y){let q=x0(Y),$=S1(Y),Z=Bun.spawnSync(["schtasks","/Delete","/TN",q,"/F"],{stdout:"pipe",stderr:"pipe"});if(Z.exitCode!==0)j(`schtasks /Delete returned non-zero (${Z.exitCode}). Task may not have existed.`);else U(`Removed scheduled task ${q}`);if(l$($))try{T0($)}catch{}}async function F6(Y){let q=x0(Y),$=Bun.spawnSync(["schtasks","/Query","/TN",q,"/V","/FO","LIST"],{stdout:"pipe",stderr:"pipe"});if($.exitCode!==0){W(`Autostart is NOT configured for agent '${Y}'`),_("Expected task",q);return}T(`Autostart Status \u2014 ${Y}`),_("Task",q),J(),console.log($.stdout.toString())}var T6={linux:{label:"systemd",install:(Y,q,$)=>V6(Y,q,$??"./agent-db"),uninstall:L6,status:O6},darwin:{label:"launchd",install:(Y,q,$)=>J6(Y,q,$??"./agent-db"),uninstall:U6,status:I6},win32:{label:"Task Scheduler",install:C6,uninstall:G6,status:F6}};function C0(){let Y=T6[G0()];if(!Y)throw Error(`Autostart is not supported on ${G0()}. Supported: linux (systemd), darwin (launchd), win32 (Task Scheduler).`);return Y}function h1(Y){let q=Y.command("autostart").description("Configure agent to auto-start on system boot");q.command("install").description("Generate and enable system service for auto-start on reboot").option("-n, --name <name>","Agent instance name","default").option("-p, --port <port>","Port to listen on","3005").option("--db-path <path>","Agent storage directory (absolute path; default: ~/.boff/vibecontrols/agents/<profile>/agent-db)").option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=C0(),H=m$($.name),Q=W6($.port),z=$.dbPath??null,L=N$(),I=(()=>{if(!z)return L;if(Q6(z))return z;let O=z6(L,"..",z);return j(`--db-path is relative; resolved to ${O}. Pass an absolute path to silence this warning.`),O})();if(!Z.json)T("Installing Autostart"),_("Platform",`${G0()} (${X.label})`),_("Agent",H),_("Port",String(Q)),_("Database",I),J();await X.install(H,Q,I),B(Z,{ok:!0,enabled:!0,name:H,port:Q})}catch(X){if(Z.json)B(Z,{ok:!1,error:String(X)}),process.exit(1);V(`Failed to install autostart: ${X}`),process.exit(1)}}),q.command("uninstall").description("Stop and remove the system service").option("-n, --name <name>","Agent instance name","default").option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=C0(),H=m$($.name);if(!Z.json)T("Removing Autostart");await X.uninstall(H),B(Z,{ok:!0,enabled:!1,name:H})}catch(X){if(Z.json)B(Z,{ok:!1,error:String(X)}),process.exit(1);V(`Failed to uninstall autostart: ${X}`),process.exit(1)}}),q.command("status").description("Check if autostart is configured and running").option("-n, --name <name>","Agent instance name","default").action(async($)=>{try{let Z=C0(),X=m$($.name);await Z.status(X)}catch(Z){V(`Failed to check autostart status: ${Z}`),process.exit(1)}})}import{existsSync as v1,readFileSync as y1,writeFileSync as R6}from"fs";import{join as f1}from"path";var P1=Q$();function b1(Y){Y.command("export").description("Export plugin config and user preferences to a JSON file").option("--plugins","Export plugin registry only").option("--config","Export config file only").option("--state","Export plugin state from agent database").option("--all","Export everything (default)").option("--include-secrets","Include API keys and gateway secrets in the export",!1).option("-o, --output <path>","Output file path").option("--agent-url <url>","Agent URL","http://localhost:3005").option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON manifest").action(async function(q){let $={...Y.opts(),...q};try{if(!$.json)T("Export Agent Configuration");let Z=q.all||!q.plugins&&!q.config&&!q.state,X=q.includeSecrets===!0;if(X&&!$.json)j("Export will include local secrets. Store the file securely."),J();let H={version:"1.0",exportedAt:new Date().toISOString()},Q=0;if(Z||q.plugins){let I=f1(P1,"plugins.json");if(v1(I))try{H.plugins=JSON.parse(y1(I,"utf-8")),Q++,W(`Exported ${Array.isArray(H.plugins)?H.plugins.length:0} plugin(s)`)}catch{j("Could not read plugin registry")}else H.plugins=[],W("No plugin registry found (empty)")}if(Z||q.config){let I=f1(P1,"config.json");if(v1(I))try{let O=JSON.parse(y1(I,"utf-8"));H.config=X?O:a(O),Q++,W(`Exported ${Object.keys(H.config||{}).length} config key(s)`)}catch{j("Could not read config file")}else H.config={},W("No config file found (empty)")}if(Z||q.state)try{let I=M(q),O=encodeURIComponent(S($));try{let G=await y(I,`/api/profiles/${O}/config`);H.agentConfig=X?G:a(G),Q++,W("Exported agent database config")}catch{j("Could not export agent config (agent may not be running)")}try{let G=await y(I,`/api/profiles/${O}/state`);H.pluginState=X?G:a(G),Q++,W("Exported plugin state")}catch{j("Could not export plugin state (agent may not be running)")}}catch{j("Agent not reachable \u2014 skipping database exports")}if(Q===0&&!H.plugins&&!H.config)V("Nothing to export.");let z=new Date().toISOString().replace(/[:.]/g,"-").replace("T","_").slice(0,19),L=q.output||`vibe-export-${z}.json`;if(R6(L,JSON.stringify(H,null,2),{encoding:"utf-8",mode:384}),B($,{ok:!0,file:L,sections:Q,version:H.version,exportedAt:H.exportedAt}))return;J(),U(`Exported to ${K.bold(L)}`),_("Sections",String(Q)),_("File",L),J()}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}V(`Export failed: ${X}`)}})}import{existsSync as k1,readFileSync as u1,writeFileSync as M0,mkdirSync as j6}from"fs";import{join as E6}from"path";var c1=Q$(),N6=new Set(["static-api-key","agentRecordId","clientId","clientSecret","workspaceId","globalGatewayUrl","workspaceGatewayUrl","scopes","port","host","logLevel","corsOrigin","dbPath","storageAdapter","registry"]);function D6(Y){let q={};for(let[$,Z]of Object.entries(Y)){if(!N6.has($)||Z===d1)continue;if(typeof Z==="string"||typeof Z==="number"||Array.isArray(Z))q[$]=Z}return q}function m1(Y){Y.command("import").description("Import plugin config and user preferences from a JSON file").argument("<file>","Path to the export JSON file").option("--install","Install plugins listed in the export",!1).option("--plugins","Import plugin registry only").option("--config","Import config file only").option("--merge","Merge with existing config instead of overwriting",!1).option("-y, --yes","Skip confirmation prompt").option("--json","Emit JSON").action(async function(q,$){let Z={...Y.opts(),...$},X=[];try{if(!Z.json)T("Import Agent Configuration");if(!k1(q))V(`File not found: ${q}`);let H;try{H=JSON.parse(u1(q,"utf-8"))}catch{V("Invalid JSON file. Expected a file created by 'vibe export'.");return}if(!H.version)V("Invalid export file: missing version field. Expected a file created by 'vibe export'.");W(`Export file version: ${H.version}`),W(`Exported at: ${H.exportedAt||"unknown"}`),J();let Q=!$.plugins&&!$.config;if(j6(c1,{recursive:!0}),!$.yes){let z=[];if((Q||$.plugins)&&H.plugins?.length)z.push(`${H.plugins.length} plugin(s)`);if((Q||$.config)&&H.config)z.push(`${Object.keys(H.config).length} config key(s)`);if(z.length===0){W("Nothing to import from this file.");return}if(console.log(` ${N.warning} Will import: ${z.join(", ")}`),!$.merge)console.log(` ${K.dim("Mode: overwrite (use --merge to merge instead)")}`);if(J(),!await T$(K.bold("Continue?"))){W("Import cancelled.");return}J()}if((Q||$.plugins)&&H.plugins){X.push("plugins");let z=E6(c1,"plugins.json");if($.merge&&k1(z))try{let L=JSON.parse(u1(z,"utf-8")),I=new Map(L.map((O)=>[O.packageName,O]));for(let O of H.plugins)I.set(O.packageName,O);M0(z,JSON.stringify(Array.from(I.values()),null,2),{encoding:"utf-8",mode:384}),U(`Merged ${H.plugins.length} plugin(s) into registry`)}catch{M0(z,JSON.stringify(H.plugins,null,2),{encoding:"utf-8",mode:384}),U(`Wrote ${H.plugins.length} plugin(s) to registry`)}else M0(z,JSON.stringify(H.plugins,null,2),{encoding:"utf-8",mode:384}),U(`Wrote ${H.plugins.length} plugin(s) to registry`);if($.install&&H.plugins.length>0){J(),W("Installing plugins...");let L=new s$,I=0,O=0;for(let G of H.plugins)try{W(`Installing ${K.bold(G.packageName)}...`),await L.install(G.packageName),U(`Installed ${K.bold(G.packageName)}`),I++}catch(x){j(`Failed to install ${G.packageName}: ${x instanceof Error?C(x):String(x)}`),O++}if(J(),_("Installed",String(I)),O>0)_("Failed",String(O))}}if((Q||$.config)&&H.config){let z=D6(H.config);if(Object.keys(z).length===0)j("No importable config keys found. Redacted secrets are skipped.");else if(U$(z),X.push("config"),!Z.json)U(`Imported ${Object.keys(z).length} config key(s)`)}if(B(Z,{ok:!0,imported:X}))return;J(),U(`${K.bold("Import complete.")} Run ${K.bold("vibe start")} to apply changes.`),J()}catch(H){let Q=H instanceof Error?C(H):String(H);if(Z.json){B(Z,{ok:!1,error:Q});return}V(`Import failed: ${Q}`)}})}import{existsSync as g1,mkdtempSync as x6,readFileSync as M6,writeFileSync as w6}from"fs";import{tmpdir as A6}from"os";import{join as n$}from"path";async function S6(Y,q){try{return await y(Y,`/api/profiles/${q}/agent/system`)}catch{return null}}async function h6(Y,q){try{return(await y(Y,`/api/profiles/${q}/agent/version`)).version??null}catch{return null}}async function v6(Y){try{return await y(Y,"/health/ready")}catch{return null}}function y6(Y,q){if(!g1(Y))return[];try{let Z=M6(Y,"utf8").split(`
202
+ </Task>`}async function C6(Y,q,$){let Z=x0(Y),X=S1(Y),H=R0(),Q=g$();A$(H,{recursive:!0}),A$(Q,{recursive:!0});let z=j0(),V=E0(),_=_6({name:Y,port:q,dbPath:$,bunPath:z,entryPoint:V,configDir:H,logsDir:Q}),O=Buffer.concat([Buffer.from([255,254]),Buffer.from(_,"utf16le")]);if(F0(X,O),I("Task XML",X),Bun.spawnSync(["schtasks","/Create","/TN",Z,"/XML",X,"/F"],{stdout:"inherit",stderr:"inherit"}).exitCode!==0)throw Error("schtasks /Create failed. Run from an elevated shell if your user lacks scheduler permission.");J(),U(`Autostart installed for agent '${Y}' (Task: ${Z})`),W("To start now without rebooting:"),W(` schtasks /Run /TN ${Z}`)}async function G6(Y){let q=x0(Y),$=S1(Y),Z=Bun.spawnSync(["schtasks","/Delete","/TN",q,"/F"],{stdout:"pipe",stderr:"pipe"});if(Z.exitCode!==0)j(`schtasks /Delete returned non-zero (${Z.exitCode}). Task may not have existed.`);else U(`Removed scheduled task ${q}`);if(l$($))try{T0($)}catch{}}async function F6(Y){let q=x0(Y),$=Bun.spawnSync(["schtasks","/Query","/TN",q,"/V","/FO","LIST"],{stdout:"pipe",stderr:"pipe"});if($.exitCode!==0){W(`Autostart is NOT configured for agent '${Y}'`),I("Expected task",q);return}T(`Autostart Status \u2014 ${Y}`),I("Task",q),J(),console.log($.stdout.toString())}var T6={linux:{label:"systemd",install:(Y,q,$)=>V6(Y,q,$??"./agent-db"),uninstall:L6,status:O6},darwin:{label:"launchd",install:(Y,q,$)=>J6(Y,q,$??"./agent-db"),uninstall:U6,status:I6},win32:{label:"Task Scheduler",install:C6,uninstall:G6,status:F6}};function C0(){let Y=T6[G0()];if(!Y)throw Error(`Autostart is not supported on ${G0()}. Supported: linux (systemd), darwin (launchd), win32 (Task Scheduler).`);return Y}function h1(Y){let q=Y.command("autostart").description("Configure agent to auto-start on system boot");q.command("install").description("Generate and enable system service for auto-start on reboot").option("-n, --name <name>","Agent instance name","default").option("-p, --port <port>","Port to listen on","3005").option("--db-path <path>","Agent storage directory (absolute path; default: ~/.boff/vibecontrols/agents/<profile>/agent-db)").option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=C0(),H=m$($.name),Q=W6($.port),z=$.dbPath??null,V=N$(),_=(()=>{if(!z)return V;if(Q6(z))return z;let O=z6(V,"..",z);return j(`--db-path is relative; resolved to ${O}. Pass an absolute path to silence this warning.`),O})();if(!Z.json)T("Installing Autostart"),I("Platform",`${G0()} (${X.label})`),I("Agent",H),I("Port",String(Q)),I("Database",_),J();await X.install(H,Q,_),B(Z,{ok:!0,enabled:!0,name:H,port:Q})}catch(X){if(Z.json)B(Z,{ok:!1,error:String(X)}),process.exit(1);L(`Failed to install autostart: ${X}`),process.exit(1)}}),q.command("uninstall").description("Stop and remove the system service").option("-n, --name <name>","Agent instance name","default").option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=C0(),H=m$($.name);if(!Z.json)T("Removing Autostart");await X.uninstall(H),B(Z,{ok:!0,enabled:!1,name:H})}catch(X){if(Z.json)B(Z,{ok:!1,error:String(X)}),process.exit(1);L(`Failed to uninstall autostart: ${X}`),process.exit(1)}}),q.command("status").description("Check if autostart is configured and running").option("-n, --name <name>","Agent instance name","default").action(async($)=>{try{let Z=C0(),X=m$($.name);await Z.status(X)}catch(Z){L(`Failed to check autostart status: ${Z}`),process.exit(1)}})}import{existsSync as v1,readFileSync as y1,writeFileSync as R6}from"fs";import{join as f1}from"path";var P1=Q$();function b1(Y){Y.command("export").description("Export plugin config and user preferences to a JSON file").option("--plugins","Export plugin registry only").option("--config","Export config file only").option("--state","Export plugin state from agent database").option("--all","Export everything (default)").option("--include-secrets","Include API keys and gateway secrets in the export",!1).option("-o, --output <path>","Output file path").option("--agent-url <url>","Agent URL","http://localhost:3005").option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON manifest").action(async function(q){let $={...Y.opts(),...q};try{if(!$.json)T("Export Agent Configuration");let Z=q.all||!q.plugins&&!q.config&&!q.state,X=q.includeSecrets===!0;if(X&&!$.json)j("Export will include local secrets. Store the file securely."),J();let H={version:"1.0",exportedAt:new Date().toISOString()},Q=0;if(Z||q.plugins){let _=f1(P1,"plugins.json");if(v1(_))try{H.plugins=JSON.parse(y1(_,"utf-8")),Q++,W(`Exported ${Array.isArray(H.plugins)?H.plugins.length:0} plugin(s)`)}catch{j("Could not read plugin registry")}else H.plugins=[],W("No plugin registry found (empty)")}if(Z||q.config){let _=f1(P1,"config.json");if(v1(_))try{let O=JSON.parse(y1(_,"utf-8"));H.config=X?O:a(O),Q++,W(`Exported ${Object.keys(H.config||{}).length} config key(s)`)}catch{j("Could not read config file")}else H.config={},W("No config file found (empty)")}if(Z||q.state)try{let _=w(q),O=encodeURIComponent(A($));try{let F=await y(_,`/api/profiles/${O}/config`);H.agentConfig=X?F:a(F),Q++,W("Exported agent database config")}catch{j("Could not export agent config (agent may not be running)")}try{let F=await y(_,`/api/profiles/${O}/state`);H.pluginState=X?F:a(F),Q++,W("Exported plugin state")}catch{j("Could not export plugin state (agent may not be running)")}}catch{j("Agent not reachable \u2014 skipping database exports")}if(Q===0&&!H.plugins&&!H.config)L("Nothing to export.");let z=new Date().toISOString().replace(/[:.]/g,"-").replace("T","_").slice(0,19),V=q.output||`vibe-export-${z}.json`;if(R6(V,JSON.stringify(H,null,2),{encoding:"utf-8",mode:384}),B($,{ok:!0,file:V,sections:Q,version:H.version,exportedAt:H.exportedAt}))return;J(),U(`Exported to ${K.bold(V)}`),I("Sections",String(Q)),I("File",V),J()}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}L(`Export failed: ${X}`)}})}import{existsSync as k1,readFileSync as u1,writeFileSync as M0,mkdirSync as j6}from"fs";import{join as E6}from"path";var c1=Q$(),N6=new Set(["static-api-key","agentRecordId","clientId","clientSecret","workspaceId","globalGatewayUrl","workspaceGatewayUrl","scopes","port","host","logLevel","corsOrigin","dbPath","storageAdapter","registry"]);function D6(Y){let q={};for(let[$,Z]of Object.entries(Y)){if(!N6.has($)||Z===d1)continue;if(typeof Z==="string"||typeof Z==="number"||Array.isArray(Z))q[$]=Z}return q}function m1(Y){Y.command("import").description("Import plugin config and user preferences from a JSON file").argument("<file>","Path to the export JSON file").option("--install","Install plugins listed in the export",!1).option("--plugins","Import plugin registry only").option("--config","Import config file only").option("--merge","Merge with existing config instead of overwriting",!1).option("-y, --yes","Skip confirmation prompt").option("--json","Emit JSON").action(async function(q,$){let Z={...Y.opts(),...$},X=[];try{if(!Z.json)T("Import Agent Configuration");if(!k1(q))L(`File not found: ${q}`);let H;try{H=JSON.parse(u1(q,"utf-8"))}catch{L("Invalid JSON file. Expected a file created by 'vibe export'.");return}if(!H.version)L("Invalid export file: missing version field. Expected a file created by 'vibe export'.");W(`Export file version: ${H.version}`),W(`Exported at: ${H.exportedAt||"unknown"}`),J();let Q=!$.plugins&&!$.config;if(j6(c1,{recursive:!0}),!$.yes){let z=[];if((Q||$.plugins)&&H.plugins?.length)z.push(`${H.plugins.length} plugin(s)`);if((Q||$.config)&&H.config)z.push(`${Object.keys(H.config).length} config key(s)`);if(z.length===0){W("Nothing to import from this file.");return}if(console.log(` ${E.warning} Will import: ${z.join(", ")}`),!$.merge)console.log(` ${K.dim("Mode: overwrite (use --merge to merge instead)")}`);if(J(),!await T$(K.bold("Continue?"))){W("Import cancelled.");return}J()}if((Q||$.plugins)&&H.plugins){X.push("plugins");let z=E6(c1,"plugins.json");if($.merge&&k1(z))try{let V=JSON.parse(u1(z,"utf-8")),_=new Map(V.map((O)=>[O.packageName,O]));for(let O of H.plugins)_.set(O.packageName,O);M0(z,JSON.stringify(Array.from(_.values()),null,2),{encoding:"utf-8",mode:384}),U(`Merged ${H.plugins.length} plugin(s) into registry`)}catch{M0(z,JSON.stringify(H.plugins,null,2),{encoding:"utf-8",mode:384}),U(`Wrote ${H.plugins.length} plugin(s) to registry`)}else M0(z,JSON.stringify(H.plugins,null,2),{encoding:"utf-8",mode:384}),U(`Wrote ${H.plugins.length} plugin(s) to registry`);if($.install&&H.plugins.length>0){J(),W("Installing plugins...");let V=new s$,_=0,O=0;for(let F of H.plugins)try{W(`Installing ${K.bold(F.packageName)}...`),await V.install(F.packageName),U(`Installed ${K.bold(F.packageName)}`),_++}catch(D){j(`Failed to install ${F.packageName}: ${D instanceof Error?C(D):String(D)}`),O++}if(J(),I("Installed",String(_)),O>0)I("Failed",String(O))}}if((Q||$.config)&&H.config){let z=D6(H.config);if(Object.keys(z).length===0)j("No importable config keys found. Redacted secrets are skipped.");else if(U$(z),X.push("config"),!Z.json)U(`Imported ${Object.keys(z).length} config key(s)`)}if(B(Z,{ok:!0,imported:X}))return;J(),U(`${K.bold("Import complete.")} Run ${K.bold("vibe start")} to apply changes.`),J()}catch(H){let Q=H instanceof Error?C(H):String(H);if(Z.json){B(Z,{ok:!1,error:Q});return}L(`Import failed: ${Q}`)}})}import{existsSync as g1,mkdtempSync as x6,readFileSync as M6,writeFileSync as w6}from"fs";import{tmpdir as A6}from"os";import{join as n$}from"path";async function S6(Y,q){try{return await y(Y,`/api/profiles/${q}/agent/system`)}catch{return null}}async function h6(Y,q){try{return(await y(Y,`/api/profiles/${q}/agent/version`)).version??null}catch{return null}}async function v6(Y){try{return await y(Y,"/health/ready")}catch{return null}}function y6(Y,q){if(!g1(Y))return[];try{let Z=M6(Y,"utf8").split(`
203
203
  `);return Z.slice(Math.max(0,Z.length-q))}catch{return[]}}function f6(){let Y=/\bvibe\b|bun/i;try{if(process.platform==="win32")return Bun.spawnSync(["tasklist","/FO","CSV","/NH"],{stdout:"pipe",stderr:"ignore"}).stdout.toString().split(/\r?\n/).filter((Z)=>Y.test(Z)).join(`
204
204
  `);return Bun.spawnSync(["sh","-c","ps -o pid,ppid,cmd | grep -E 'vibe|bun' | grep -v grep"],{stdout:"pipe",stderr:"ignore"}).stdout.toString()}catch{return""}}function P6(Y){let q=[];return q.push({name:"Agent /health/ready",ok:Y.health!==null,message:Y.health!==null?"reachable":"not reachable",detail:Y.health!==null?JSON.stringify(Y.health,null,2):"Health endpoint did not respond."}),q.push({name:"Agent version",ok:Y.agent.version!==null,message:Y.agent.version??"(unknown)",detail:`Agent URL: ${Y.agent.agentUrl}
205
205
  Version: ${Y.agent.version??"n/a"}`}),q.push({name:"System snapshot",ok:Y.system!==null,message:Y.system?`${Y.system.platform??"?"} ${Y.system.arch??""}`.trim():"unavailable",detail:Y.system?JSON.stringify(Y.system,null,2):"Could not query /api/agent/system."}),q.push({name:"Agent config",ok:Object.keys(Y.config).length>0,message:`${Object.keys(Y.config).length} key(s) (redacted)`,detail:JSON.stringify(Y.config,null,2)}),q.push({name:"Log file",ok:Y.logsTail.length>0,message:`${Y.logFile} (${Y.logsTail.length} lines)`,detail:Y.logsTail.slice(-50).join(`
206
206
  `)||"(empty)"}),q.push({name:"Related processes",ok:Y.processes.split(`
207
207
  `).filter(Boolean).length>0,message:`${Y.processes.split(`
208
- `).filter(Boolean).length} process(es)`,detail:Y.processes||"(none found)"}),q}function l1(Y){Y.command("diagnostics").alias("diag").description("Collect a redacted diagnostic dump for support").option("--agent-url <url>","Agent URL (default http://localhost:3005)","http://localhost:3005").option("--lines <n>","Tail this many log lines","1000").option("--out <path>","Write JSON dump to file").option("--json","Emit JSON to stdout").option("--plain","Force plain text output").action(async function(q){try{let $={...Y.opts(),...q},Z=M($),X=encodeURIComponent(S($)),H=Number.parseInt($.lines??"1000",10)||1000;await b({mode:f($),fetchData:async()=>{let[Q,z,L]=await Promise.all([S6(Z,X),h6(Z,X),v6(Z)]),I=q$(),O=a(I),G=n$(Q$(),"logs"),F=["default.log","agent.log"].map((D)=>n$(G,D)).find((D)=>g1(D))??n$(G,"default.log"),R=y6(F,H),E={timestamp:new Date().toISOString(),agent:{version:z,agentUrl:Z},system:Q,health:L,config:O,processes:f6(),logFile:F,logsTail:R},w=P6(E);return{dump:E,probes:w}},plain:(Q)=>{T("VibeControls Agent Diagnostics"),J(),W("Collecting agent state\u2026");let z=$.out?$.out:n$(x6(n$(A6(),"vibe-diag-")),`vibe-diagnostics-${Date.now()}.json`);w6(z,JSON.stringify(Q.dump,null,2),"utf8"),_("Wrote",K.bold(z)),_("Log lines",String(Q.dump.logsTail.length)),_("Processes",String(Q.dump.processes.split(`
209
- `).filter(Boolean).length)),J(),U("Diagnostics complete. Attach the JSON to your support ticket.")},interactive:async(Q)=>{let z=Q.probes.map((I,O)=>({id:`${O}-${I.name}`,label:I.name,hint:I.ok?"ok":"fail",detail:[`${I.ok?K.green("\u2714 ok"):K.red("\u2718 fail")} ${K.bold(I.name)}`,"",I.message,...I.detail?["",I.detail]:[]].join(`
210
- `)})),L=Q.probes.filter((I)=>I.ok).length;await e({title:`Vibe Diagnostics \u2014 ${L}/${Q.probes.length} ok`,rows:z,footer:"\u2191/\u2193 navigate \xB7 q to quit"})},json:(Q)=>({checks:Q.probes.map((z)=>({name:z.name,ok:z.ok,message:z.message})),dump:Q.dump})})}catch($){V(`Diagnostics failed: ${$ instanceof Error?C($):String($)}`)}})}import{existsSync as h$,readFileSync as m6,readdirSync as g6,renameSync as l6,rmSync as S0,statSync as n6,writeFileSync as i6}from"fs";import{join as i}from"path";import{existsSync as j$,readdirSync as b6,rmSync as k6,statSync as u6}from"fs";import{dirname as H0,join as z$}from"path";var R$="@vibecontrols";function c6(){let q=l().npmGlobalBin();if(!q)return null;let $=z$(H0(q),"lib","node_modules");if(j$($))return $;let Z=z$(H0(q),"node_modules");if(j$(Z))return Z;let X=z$(H0(q),"..","node_modules");if(j$(X))return X;return null}function d6(){let Y=l(),q=Y.bunGlobalBin();if(q){let $=z$(H0(q),"node_modules");if(j$($))return $;let Z=z$(Y.homeDir,".bun","install","global","node_modules");if(j$(Z))return Z}return null}function n1(Y){let q=z$(Y,R$);if(!j$(q))return[];try{return b6(q).filter(($)=>{if($.startsWith("."))return!1;try{return u6(z$(q,$)).isDirectory()}catch{return!1}})}catch{return[]}}function i1(){let Y=[],q=d6();if(q)for(let Z of n1(q))Y.push({packageName:`${R$}/${Z}`,root:"bun",rootDir:z$(q,R$)});let $=c6();if($)for(let Z of n1($))Y.push({packageName:`${R$}/${Z}`,root:"npm",rootDir:z$($,R$)});return Y}function p1(Y,q){if(q.dryRun)return{packageName:Y.packageName,root:Y.root,ok:!0,via:"skip"};let $=l();if(Y.root==="bun"){let X=$.platform==="win32"?"bun.exe":"bun";try{if(Bun.spawnSync([X,"remove","-g",Y.packageName],{timeout:60000,stdout:"pipe",stderr:"pipe"}).exitCode===0)return{packageName:Y.packageName,root:Y.root,ok:!0,via:"bun"}}catch{}}else{let X=$.platform==="win32"?"npm.cmd":"npm";try{if(Bun.spawnSync([X,"uninstall","-g",Y.packageName],{timeout:120000,stdout:"pipe",stderr:"pipe"}).exitCode===0)return{packageName:Y.packageName,root:Y.root,ok:!0,via:"npm"}}catch{}}let Z=z$(Y.rootDir,Y.packageName.slice(R$.length+1));try{if(j$(Z))k6(Z,{recursive:!0,force:!0});return{packageName:Y.packageName,root:Y.root,ok:!0,via:"rm"}}catch(X){return{packageName:Y.packageName,root:Y.root,ok:!1,via:"rm",error:X instanceof Error?X.message:String(X)}}}var w0=`${R$}/agent`;function o1(Y){return Y===w0}var p6=new Set(["db","plugins-registry","logs","binaries","subprocs"]);function o6(Y){let q=new Set,$=[];if(!Y)return{keep:q,unknown:$};for(let Z of Y.split(",").map((X)=>X.trim()).filter(Boolean))if(p6.has(Z))q.add(Z);else $.push(Z);return{keep:q,unknown:$}}var a6=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function t6(Y,q){if(!a6.test(q))return!1;let $=i(Y,q);try{return n6($).isDirectory()}catch{return!1}}function s6(){let Y=V$();if(!h$(Y))return[];return g6(Y).filter((q)=>t6(Y,q)).map((q)=>({profile:q,agentDir:i(Y,q)}))}function r6(){let Y=process.env.VIBECONTROLS_PROFILE||"default";return{profile:Y,agentDir:i(V$(),Y)}}function e6(Y){if(!Y)return[];return Y.split(",").map((q)=>q.trim()).filter(Boolean)}function $3(Y){let q=[],$=[],Z=[];for(let X of Y){let H=s1(X);if(!H){$.push(X);continue}let Q={packageName:H.packageName,pluginName:H.pluginName,isCore:!!H.isCore,raw:X};if(Q.isCore)Z.push(Q);else q.push(Q)}return{resolved:q,unknown:$,bundled:Z}}async function Y3(){return(await import("./subprocess-g9sk1ep9.js")).killAllTracked()}function q3(Y,q){let $=J$(Y);if(!$||typeof $.pid!=="number"||$.pid<=0)return{killed:0,skipped:0};let Z=l();if(!Z.isProcessAlive($.pid)){if(!q)X$(Y);return{killed:0,skipped:1}}if(q)return W(` would kill tunnel pid ${$.pid} (${$.provider}) from ${K.dim(Y)}`),{killed:1,skipped:0};let X=Z.killProcessTree($.pid,"SIGTERM");if(X&&Z.isProcessAlive($.pid))Z.killProcessTree($.pid,"SIGKILL");return X$(Y),{killed:X?1:0,skipped:X?0:1}}function e1(){return i(l().homeDir,".bun","install","global")}function $2(Y,q){let $=e1(),Z=i($,"package.json"),X=i($,"bun.lock");if(!h$(Z))return{droppedCount:0,manifestPath:Z,lockPath:X};let H=typeof Y==="function"?Y:(x)=>x===Y,Q;try{Q=m6(Z,"utf8")}catch{return{droppedCount:0,manifestPath:Z,lockPath:X}}let z;try{z=JSON.parse(Q)}catch{return{droppedCount:0,manifestPath:Z,lockPath:X}}if(!z.dependencies||typeof z.dependencies!=="object")return{droppedCount:0,manifestPath:Z,lockPath:X};let L=Object.keys(z.dependencies),I={};for(let x of L)if(!H(x))I[x]=z.dependencies[x];let O=L.length-Object.keys(I).length;if(O===0)return{droppedCount:0,manifestPath:Z,lockPath:X};if(q)return W(` would drop ${O} dep(s) from ${K.dim(Z)} and remove ${K.dim(X)}`),{droppedCount:O,manifestPath:Z,lockPath:X};z.dependencies=I;let G=`${Z}.${process.pid}.tmp`;if(i6(G,`${JSON.stringify(z,null,2)}
211
- `,{encoding:"utf8"}),l6(G,Z),h$(X))try{S0(X,{force:!0})}catch{}return{droppedCount:O,manifestPath:Z,lockPath:X}}async function _$(Y,q){if(!h$(Y))return;if(q){W(` would remove ${K.dim(Y)}`);return}try{S0(Y,{recursive:!0,force:!0})}catch($){j(`Failed to remove ${Y}: ${$ instanceof Error?C($):String($)}`)}}async function Z3(Y,q,$){if(q)return W(` would uninstall plugin ${K.bold(Y)}`),!0;if($)try{if((await fetch(`${$}/api/plugins/remove`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({packageName:Y})})).ok)return!0}catch{}try{let H=l(),Q=H.which("bun")??`bun${H.executableSuffix}`;if(Bun.spawnSync([Q,"remove","-g",Y],{timeout:60000,stdout:"pipe",stderr:"pipe"}).exitCode===0)return!0}catch{}let Z=i(e1(),"node_modules",Y),X=!1;try{if(h$(Z))S0(Z,{recursive:!0,force:!0}),X=!0}catch{}$2(Y,!1);try{let{pruneStaleBunBinShims:H}=await import("./prune-stale-shims-nkx9vq5m.js");H()}catch{}return X||!0}async function X3(Y,q){try{let $=await fetch(`${Y}/api/plugins/prereqs/uninstall`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({packageName:q})});if(!$.ok)return{ok:!1,pendingSudo:[]};let Z=await $.json();return{ok:!!Z.ok,pendingSudo:Z.pendingSudo??[]}}catch{return{ok:!1,pendingSudo:[]}}}async function H3(Y,q,$){try{let Z=await fetch(`${Y}/api/plugins/nuke`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(q?{packageName:q,dryRun:$}:{dryRun:$})});if(!Z.ok)return[];let X=await Z.json(),H=[];for(let Q of X.results??[]){if(Q.error){H.push(`${Q.plugin} (failed: ${Q.error})`);continue}for(let z of Q.reaped??[])H.push(`${Q.plugin}: ${z}`)}return H}catch{return[]}}async function Q3(Y,q){T(`Nuking agent: ${Y.profile}`),_("Path",Y.agentDir);let $=null;try{let X=(await q.serviceManager.listInstances()).find((H)=>H.name===Y.profile);if(X?.status==="running"){if($=`http://localhost:${X.config?.port??3005}`,(!q.keep.has("binaries")||!q.keep.has("subprocs"))&&(q.nukeAllPlugins||q.removePlugins.length>0)){let z=q.nukeAllPlugins?[void 0]:q.removePlugins.map((L)=>L.packageName);for(let L of z){let I=await H3($,L,q.dryRun);for(let O of I)if(q.dryRun)W(` would nuke \u2192 ${O}`);else U(`Plugin nuke \u2192 ${O}`)}}if(q.dryRun)W(` would stop running agent ${K.bold(Y.profile)}`);else try{await q.serviceManager.stop(Y.profile),U(`Stopped ${K.bold(Y.profile)}`)}catch(z){j(`Failed to stop ${Y.profile}: ${z}`)}}}catch{}if(!q.dryRun&&!q.keep.has("subprocs"))try{let{reaped:X}=await Y3();if(X>0)U(`Reaped ${X} tracked subprocess(es)`)}catch{}else if(q.keep.has("subprocs"))W(" keeping tracked subprocesses (--keep includes subprocs)");if(!q.keep.has("subprocs"))try{let{killed:X}=q3(Y.agentDir,q.dryRun);if(X>0&&!q.dryRun)U(`Killed persisted tunnel subprocess for ${Y.profile}`)}catch(X){j(`Failed to kill tunnel for ${Y.profile}: ${X instanceof Error?C(X):String(X)}`)}let Z=[];if(!q.keep.has("binaries")){let X=r1(Y.agentDir),H=new Map;for(let Q of X){let z=H.get(Q.pluginPackageName)??[];z.push(Q),H.set(Q.pluginPackageName,z)}if(H.size===0)W(" no agent-installed prerequisites tracked");else if(!$)j(` agent not running \u2014 cannot call prereqs/uninstall on ${H.size} plugin(s); rerun with the agent up to clean binaries`);else for(let[Q,z]of H){if(q.dryRun){W(` would call prereqs/uninstall on ${K.bold(Q)} (${z.length} item(s))`);continue}let L=await X3($,Q);if(L.ok)U(`Uninstalled prereqs for ${Q}`);else j(`Plugin ${Q} did not implement prereqs/uninstall`);for(let I of L.pendingSudo)Z.push(I)}}else W(" keeping installed binaries (--keep includes binaries)");for(let X of q.removePlugins)if(await Z3(X.packageName,q.dryRun,$))U(`Removed plugin ${X.packageName}`);else j(`Failed to remove plugin ${X.packageName}`);if(q.nukeAllPlugins||!q.keep.has("plugins-registry"))await _$(i(Y.agentDir,"agent-plugins"),q.dryRun);else W(" keeping local agent-plugins store (--keep includes plugins-registry)");if(!q.keep.has("db"))await _$(i(Y.agentDir,"agent-db"),q.dryRun);else W(" keeping encrypted DB (--keep includes db)");if(!q.keep.has("plugins-registry"))await _$(i(Y.agentDir,"plugins.json"),q.dryRun),await _$(i(Y.agentDir,"prereqs-installed.json"),q.dryRun);else W(" keeping plugins.json + prereqs-installed.json (--keep includes plugins-registry)");if(!q.keep.has("logs"))await _$(i(Y.agentDir,"logs"),q.dryRun);else W(" keeping log files (--keep includes logs)");if(q.removeConfig)await _$(i(Y.agentDir,"config.json"),q.dryRun),U(`Removed config.json for ${Y.profile}`);return{pendingSudo:Z}}function Y2(Y){Y.command("nuke").description("Cleanly remove agent state, tracked binaries, and (optionally) plugins/config across one or all agents.").option("--remove-plugins <csv>","Comma-separated plugin names (short or full) to uninstall").option("--remove-config","Also delete config.json").option("--all","Apply to every agent under .boff/vibecontrols/agents/ and wipe all external provider plugins").option("--keep <csv>","Comma-separated list of things to preserve. Valid: db, plugins-registry, logs, binaries, subprocs").option("--dry-run","Print what would happen without doing it").option("-y, --yes","Skip the confirmation prompt").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=q.all?s6():[r6()].filter((R)=>h$(R.agentDir));if(Z.length===0){W("Nothing to nuke \u2014 no agent state directories found.");return}let X=e6(q.removePlugins),{resolved:H,unknown:Q,bundled:z}=$3(X);if(Q.length>0){V(`Unknown plugin(s): ${Q.join(", ")} \u2014 try the full @vibecontrols/* package name`);return}if(z.length>0)for(let R of z)j(`Skipping ${K.bold(R.packageName)}: bundled with the agent (uninstall the agent itself with \`npm uninstall -g @vibecontrols/agent\`)`);let{keep:L,unknown:I}=o6(q.keep);if(I.length>0){V(`Unknown --keep value(s): ${I.join(", ")} \u2014 valid: db, plugins-registry, logs, binaries, subprocs`);return}if(T(q.dryRun?"Dry-run nuke":"Nuke"),W(`Agents: ${Z.map((R)=>R.profile).join(", ")}`),W(`Plugins: ${H.map((R)=>R.packageName).join(", ")||"(none)"}`),W(`Remove config: ${q.removeConfig?"yes":"no"}`),W(`Keep: ${L.size>0?[...L].sort().join(", "):"(nothing)"}`),W(`Wipe bun-global @vibecontrols/*: ${q.all?"yes":"no"}`),J(),!q.yes&&!q.dryRun){if(!await T$(K.bold("This will permanently delete the listed state. Continue?"))){W("Cancelled.");return}J()}let O=new o,G=[];for(let R of Z){let{pendingSudo:E}=await Q3(R,{serviceManager:O,removePlugins:H,nukeAllPlugins:!!q.all,removeConfig:!!q.removeConfig,keep:L,dryRun:!!q.dryRun});for(let w of E)G.push(w);J()}let x=[],F=null;if(q.all){try{if(q.dryRun){let D=await A0();F=D,W(` would clear ${D.count} secret(s) from ${D.backend}`)}else{let D=await A0(),A=!0;if(D.count>0&&!q.yes)A=await T$(K.bold(`About to remove ${D.count} secret(s) from ${D.backend}. Continue?`));if(A)if(F=await a1(),F.count>0)U(`Cleared ${F.count} secret(s) from ${F.backend}`);else W(" no secrets to clear");else W(" skipped clearing secrets (user declined)"),F={count:0,backend:"none",names:[]}}}catch(D){j(`Failed to clear secrets: ${D instanceof Error?C(D):String(D)}`)}let R=i1().filter((D)=>!o1(D.packageName));if(R.length===0)W(" no @vibecontrols/* packages found in bun-global / npm-global");else{W(` found ${R.length} @vibecontrols/* package(s) in global roots`);for(let D of R){let A=p1(D,{dryRun:!!q.dryRun});if(x.push(A),q.dryRun)W(` would uninstall ${K.bold(D.packageName)} (${D.root}-global)`);else if(A.ok)U(`Removed ${D.packageName} (${D.root}-global, via ${A.via})`);else j(`Failed to remove ${D.packageName} (${D.root}-global): ${A.error??"unknown"}`)}}let{droppedCount:E,manifestPath:w}=$2((D)=>D.startsWith("@vibecontrols/")&&D!==w0,!!q.dryRun);if(E>0&&!q.dryRun)U(`Dropped ${E} @vibecontrols/* dep(s) from ${w}`);await _$(i(Z$(),"agents.json"),!!q.dryRun),await _$(i(Z$(),".consent.json"),!!q.dryRun)}if(G.length>0){J(),j(`${G.length} command(s) require sudo to fully uninstall:`);for(let R of G)_(` ${R.name}`,R.command)}if(B($,{ok:!0,deleted:Z.map((R)=>R.profile),removedGlobalPackages:x,clearedSecrets:F,dryRun:!!q.dryRun}))return;if(q.all&&x.length>0&&!q.dryRun){let R=x.filter((E)=>E.ok).length;J(),W(`${N.info} Uninstalled ${R}/${x.length} global @vibecontrols/* package(s)`)}if(J(),U(q.dryRun?"Dry-run complete.":"Nuke complete."),q.all&&!q.dryRun)W(`${N.info} To remove the agent itself: ${K.bold("npm uninstall -g @vibecontrols/agent")} (or ${K.bold("bun remove -g @vibecontrols/agent")})`)}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}V(X)}})}import{existsSync as z3}from"fs";import{platform as W3}from"os";var K3="http://localhost:3005";function q2(Y){if(Y==="pass")return K.green("\u2714 pass");if(Y==="warn")return K.yellow("\u26A0 warn");return K.red("\u2718 fail")}async function V3(Y){try{return await y(Y,"/health"),{name:"Agent HTTP reachable",grade:"pass",message:Y}}catch(q){return{name:"Agent HTTP reachable",grade:"fail",message:C(q),hint:"Run `vibe start` (or check `vibe status` if it should already be running)."}}}async function L3(){try{let Y="default";try{Y=Y0()}catch{}let q=await Z2(`${Y}:static-api-key`),$=q$();if(!Boolean(q||$["static-api-key"]||process.env.AGENT_API_KEY))return{name:"Agent config / API key",grade:"warn",message:"No persistent API key set; agent will mint a fresh one each restart.",hint:"Run `vibe config --set static-api-key=true` to persist."};return{name:"Agent config / API key",grade:"pass",message:"config.json present, API key persisted"}}catch(Y){return{name:"Agent config / API key",grade:"fail",message:C(Y)}}}function O3(){let Y=Q$();if(!z3(Y))return{name:"Agent working directory",grade:"warn",message:`${Y} does not exist (will be created on first start)`};return{name:"Agent working directory",grade:"pass",message:Y}}async function B3(Y,q){try{if((await y(Y,`/api/profiles/${q}/agent/gateway-auth`))?.configured)return{name:"Gateway OAuth",grade:"pass",message:"configured"};return{name:"Gateway OAuth",grade:"warn",message:"not configured \u2014 agent works locally but won't sync with platform",hint:"Add the agent on the VibeControls platform and paste the credentials."}}catch{return{name:"Gateway OAuth",grade:"warn",message:"could not query agent for gateway-auth state"}}}async function J3(Y,q){try{let $=await y(Y,`/api/profiles/${q}/plugins`),Z=$?.plugins??$??[],X=Z.filter((H)=>H.status==="error"||H.status==="failed");if(X.length>0)return{name:"Plugin registry",grade:"fail",message:`${X.length} plugin(s) failed to load`,hint:X.map((H)=>H.name??H.packageName).join(", ")};return{name:"Plugin registry",grade:"pass",message:`${Z.length} plugin(s) loaded cleanly`}}catch{return{name:"Plugin registry",grade:"warn",message:"could not query agent for plugin list"}}}function U3(){let Y=W3();if(!["linux","darwin","win32"].includes(Y))return{name:"OS runtime",grade:"warn",message:`${Y} is not officially supported (linux, darwin, win32)`};let $=typeof Bun<"u"?Bun.version:null;if(!$)return{name:"OS runtime",grade:"warn",message:`${Y} / no Bun runtime detected`};return{name:"OS runtime",grade:"pass",message:`${Y} / Bun ${$}`}}function H2(Y){Y.command("doctor").description("Run a graded health check across the agent's subsystems").option("--agent-url <url>","Agent URL",K3).option("--profile <name>","Target a specific profile by name").option("--json","Emit machine-readable JSON instead of grading text").option("--plain","Force plain text output").action(async function(q){let $={...Y.opts(),...q},Z=M($),X=encodeURIComponent(S($)),H=[];if(await b({mode:f($),fetchData:async()=>{let Q=[];Q.push(U3()),Q.push(O3()),Q.push(await L3()),Q.push(await V3(Z)),Q.push(await B3(Z,X)),Q.push(await J3(Z,X));let z=X2();for(let L of z.getDoctorChecks())try{let I=await L.run();for(let O of I){let G=O.ok?"pass":O.grade??"fail";Q.push({name:O.name,grade:G,message:O.message,hint:O.hint})}}catch(I){Q.push({name:`${L.source}: doctor contributor`,grade:"warn",message:`contributor threw: ${I.message}`})}return H=Q,Q},plain:(Q)=>{T("Vibe Doctor"),J();for(let O of Q)if(console.log(`${q2(O.grade)} ${K.bold(O.name)}`),console.log(` ${O.message}`),O.hint)console.log(` ${K.dim("\u2192 "+O.hint)}`);J();let z=Q.filter((O)=>O.grade==="fail").length,L=Q.filter((O)=>O.grade==="warn").length,I=Q.filter((O)=>O.grade==="pass").length;if(W(`${I} pass, ${L} warn, ${z} fail`),z>0)V("Doctor found problems. See hints above."),process.exitCode=1;else if(L>0)W("Doctor finished with warnings.");else U("All checks pass.")},interactive:async(Q)=>{let z=Q.map((G,x)=>{let F=[`${q2(G.grade)} ${K.bold(G.name)}`,"",G.message];if(G.hint)F.push(""),F.push(K.dim("\u2192 "+G.hint));return{id:`${x}-${G.name}`,label:G.name,hint:G.grade==="pass"?"ok":G.grade,detail:F.join(`
212
- `)}}),L=Q.filter((G)=>G.grade==="fail").length,I=Q.filter((G)=>G.grade==="warn").length,O=Q.filter((G)=>G.grade==="pass").length;if(await e({title:`Vibe Doctor \u2014 ${O} pass, ${I} warn, ${L} fail`,rows:z,footer:"\u2191/\u2193 navigate \xB7 q to quit"}),L>0)process.exitCode=1},json:(Q)=>({checks:Q.map((z)=>({name:z.name,ok:z.grade==="pass",grade:z.grade,message:z.message,hint:z.hint??null}))})}),H.some((Q)=>Q.grade==="fail"))process.exitCode=1})}var I3="http://localhost:3005",h0=new Set(["debug","info","warn","error","silent"]);function Q2(Y){Y.command("log-level [level]").description("Show or update the running agent's log level").option("--agent-url <url>","Agent URL",I3).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function(q,$){try{let Z={...Y.opts(),...$},X=M(Z),H=encodeURIComponent(S(Z));if(!q){await b({mode:f(Z),fetchData:async()=>{return{level:(await y(X,`/api/profiles/${H}/agent/log-level`))?.level??"(unknown)"}},plain:(z)=>{T("Agent Log Level"),_("Current",z.level)},interactive:async(z)=>{await v$({title:"Agent Log Level",body:`Current: ${z.level}`,footer:"press q to exit"})}});return}let Q=q.toLowerCase();if(!h0.has(Q)){if(!B(Z,{ok:!1,error:`Invalid log level: ${q}`,valid:[...h0]}))V(`Invalid log level: ${q}. Use one of: ${[...h0].join(", ")}`);return}if(await m(X,`/api/profiles/${H}/agent/log-level`,{level:Q}),B(Z,{ok:!0,level:Q}))return;U(`Log level set to ${Q}`)}catch(Z){if(B({json:!!$.json},{ok:!1,error:C(Z)}))return;V(C(Z))}})}import{existsSync as z2,readdirSync as W2,statSync as K2,unlinkSync as _3}from"fs";import{join as v0}from"path";function C3(){let Y=V$();if(!z2(Y))return[];return W2(Y).map((q)=>v0(Y,q)).filter((q)=>K2(q).isDirectory())}function G3(Y,q,$){let Z=v0(Y,"logs");if(!z2(Z))return{count:0,bytes:0};let X=Date.now()-q*86400000,H=0,Q=0;for(let z of W2(Z)){let L=v0(Z,z),I=K2(L);if(!I.isFile())continue;if(I.mtimeMs>X)continue;if(H+=1,Q+=I.size,!$)try{_3(L)}catch{}}return{count:H,bytes:Q}}function F3(Y,q){let $=J$(Y);if(!$)return 0;if(B$($.pid))return 0;if(!q)X$(Y);return 1}function V2(Y){Y.command("gc").description("Garbage-collect stale agent state (tunnel files, old logs)").option("--keep-days <n>","Keep log files newer than N days","14").option("--dry-run","Show what would be removed without changing anything",!1).option("-y, --yes","Skip the confirmation prompt (for scripts/CI)",!1).option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};if(!q.dryRun&&!await q0($,"Remove stale agent state now?")){W("Aborted.");return}try{let Z=Number(q.keepDays);if(!Number.isFinite(Z)||Z<0){if($.json){B($,{ok:!1,error:`Invalid --keep-days: ${q.keepDays}`});return}V(`Invalid --keep-days: ${q.keepDays}`);return}let X=Boolean(q.dryRun);if(!$.json)T(X?"vibe gc (dry-run)":"vibe gc"),J();let H={staleTunnelStates:0,oldLogFiles:0,bytesFreed:0},Q=[];for(let z of C3()){let L=F3(z,X);H.staleTunnelStates+=L;let I=G3(z,Z,X);if(H.oldLogFiles+=I.count,H.bytesFreed+=I.bytes,L>0||I.count>0)Q.push(z)}if(B($,{ok:!0,removed:Q,staleTunnelStates:H.staleTunnelStates,oldLogFiles:H.oldLogFiles,freedBytes:H.bytesFreed,dryRun:X}))return;if(_("Stale tunnel state files",String(H.staleTunnelStates)),_("Old log files",String(H.oldLogFiles)),_("Bytes freed",`${(H.bytesFreed/1048576).toFixed(2)} MiB`),J(),X)W(K.dim("dry-run: no files were removed"));else U("gc complete")}catch(Z){if($.json){B($,{ok:!1,error:C(Z)});return}V(C(Z))}})}async function Q0(Y,q,$,Z){W(`\u2192 ${$}`);let X=await Y.run(q,{timeoutMs:Z});if(X.code!==0)throw j(X.stderr.slice(0,600)),Error(`${$} failed (exit ${X.code})`);return X.stdout}function O2(Y){Y.command("deploy <target>").description("Install + auto-configure the VibeControls agent on a remote target (defaults to SSH)").option("--version <version>","Pin a specific agent version (default: latest)").option("--registry <url>","npm registry (default: https://registry.npmjs.org/)").option("-i, --identity-file <path>","SSH identity file (override ssh_config)").option("--label <label>","Friendly name to record this peer under (default: target host)").option("--permissions <list>","Permissions to grant ourselves on the new peer (comma-separated)","tunnel:read,session:list,plugin:list,diagnostics:read").option("--expires-in <duration>","TTL for the minted peer key (default: no expiry)").option("--install-plugins <list>","Comma-separated plugin packages to also install on the remote agent").option("--autostart","Run `vibe autostart install` on the remote agent",!1).option("--no-bun","Skip Bun runtime install on the remote (default: best-effort)").option("--confirm","Required to proceed (no destructive ops; this is a sanity gate)").option("--json","Emit JSON").action(async function(q,$){let Z={...Y.opts(),...$};try{if(!$.confirm){V("Pass --confirm to proceed. `vibe deploy` runs npm install on the remote host.");return}let X=L2(q,{identityFile:$.identityFile});T(`vibe deploy \u2192 ${X.id}`),J(),W("Probing remote host\u2026");let H=await X.probe();if(_("Remote OS",H.os??"(unknown)"),_("Remote arch",H.arch??"(unknown)"),H.npm)_("Remote npm",H.npm);if(H.bun)_("Remote bun",H.bun);if(H.vibe)_("Remote vibe (existing)",H.vibe);if(J(),!H.npm&&!H.bun){if($.bun===!1){V("Neither npm nor bun found and --no-bun was passed. Install Node.js manually, then re-run.");return}W("Installing Bun on remote\u2026");let D=await X.run(["sh","-c",`curl -fsSL https://bun.sh/install | bash && echo 'export PATH="$HOME/.bun/bin:$PATH"' >> ~/.bashrc`],{timeoutMs:300000});if(D.code!==0){j(D.stderr.slice(0,500)),V("Bun auto-install failed. Install Node.js or Bun manually, then re-run.");return}let A=await X.run(["sh","-c","$HOME/.bun/bin/bun --version 2>/dev/null"],{timeoutMs:1e4});if(A.code===0&&A.stdout.trim())H.bun="$HOME/.bun/bin/bun",_("Remote bun (installed)",A.stdout.trim());else{V("Bun installer ran but the binary isn't reachable. Manual investigation needed.");return}}else if(!H.bun&&$.bun!==!1)W("Installing Bun on remote (best-effort)\u2026"),await X.run(["sh","-c","curl -fsSL https://bun.sh/install | bash"],{timeoutMs:300000}).catch(()=>{});let Q=$.version??"latest",z=$.registry??"https://registry.npmjs.org/",L=H.npm?"npm":"bun";await Q0(X,L==="npm"?["npm","install","-g",`@vibecontrols/agent@${Q}`,`--registry=${z}`]:["sh","-c",`export PATH="$HOME/.bun/bin:$PATH"; bun install -g @vibecontrols/agent@${Q} --no-cache`],`Installing @vibecontrols/agent@${Q} via ${L}`,600000);let I='export PATH="$HOME/.bun/bin:$PATH"; ',O=await Q0(X,["sh","-c",`${I}vibe --version`],"Verifying remote vibe binary",15000);if(_("Remote agent version",O.trim()),$.autostart)await Q0(X,["sh","-c",`${I}vibe autostart install`],"Installing autostart unit",60000);if($.installPlugins)for(let D of $.installPlugins.split(",").map((A)=>A.trim()).filter(Boolean))await Q0(X,["sh","-c",`${I}vibe plugin install ${D}`],`Installing plugin ${D}`,300000);W("Starting remote agent in daemon mode\u2026"),await X.run(["sh","-c",`${I}vibe start`],{timeoutMs:60000}),W("Waiting for remote tunnel\u2026");let G=null,x=$.expiresIn?` --expires-in ${$.expiresIn}`:"",F=$.label??X.id,R=$.permissions??"tunnel:read";for(let D=0;D<15;D++){let A=await X.run(["sh","-c",`${I}vibe peer-bootstrap --label '${F.replace(/'/g,"")}' --scope ${R}${x} 2>/dev/null`],{timeoutMs:15000});if(A.code===0){let s=A.stdout,p=s.indexOf("{"),v=s.lastIndexOf("}");if(p>=0&&v>p){let P=s.slice(p,v+1);try{JSON.parse(P),G=P;break}catch{}}}await new Promise((s)=>setTimeout(s,2000))}if(!G){j("Could not run `vibe peer-bootstrap` on the remote. The agent is installed but not registered as a peer. Run `vibe network add ...` manually with the remote's API key + tunnel URL.");return}let E;try{E=JSON.parse(G)}catch(D){j(`Could not parse peer-bootstrap output: ${D.message}`);return}if(!E.tunnelUrl)j("Remote agent has no tunnel URL yet \u2014 it may still be coming up. Re-run `vibe network test <id>` later.");if(z0({id:E.id,label:F,tunnelUrl:E.tunnelUrl??"",apiKey:E.apiKey,permissions:E.permissions,addedAt:new Date().toISOString(),agentRecordId:E.agentRecordId??void 0,workspaceId:E.workspaceId??void 0,fingerprint:E.id}),B(Z,{ok:!0,host:q,version:O.trim(),peerId:E.id,tunnelUrl:E.tunnelUrl??null}))return;if(J(),U(`Deployed agent + registered peer ${E.id}`),_("Remote tunnel",E.tunnelUrl??"(pending)"),_("Permissions",E.permissions.join(",")),E.expiresAt)_("Key expires",E.expiresAt);J(),W(`${K.dim("Try it")}: ${K.bold(`vibe network test ${E.id.substring(0,8)}`)}`);let w=await W0(E.id,"/api/profiles/default/agent/identity",{operation:"post-deploy-probe"});if(w.ok)U("Peer probe succeeded.");else j(`Peer probe failed: ${w.status} ${w.error??""}. Tunnel may still be warming up.`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(C(X))}})}function B2(Y){let q=Y.split(",").map((Z)=>Z.trim()).filter(Boolean),$=K0(q);if($.length!==q.length)throw Error(`Invalid permission(s). Allowed: ${E$.join(",")}`);return $}function y0(Y){let{apiKey:q,...$}=Y;return a({...$,apiKey:"[REDACTED]"})}function C2(Y){let q=Y.command("network").description("Manage the mesh of peer agents this agent talks to");q.command("list").description("List configured peer agents").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){try{let Z={...Y.opts(),...$};await b({mode:f(Z),fetchData:()=>J2(),plain:(X)=>{if(X.length===0){W("No peers configured. Add one via `vibe deploy <ssh-target>` or `vibe network add`.");return}T("Peer agents"),n(X.map((H)=>({ID:H.id.substring(0,8),Label:H.label,Tunnel:H.tunnelUrl,Permissions:H.permissions.join(","),Last_Reachable:H.lastReachable??"never"})))},interactive:async(X)=>{if(X.length===0){T("Peer agents"),J(),W("No peers configured. Add one via `vibe deploy <ssh-target>` or `vibe network add`.");return}let H=X.map((Q)=>{let z=[`${K.bold(Q.label)} ${Q.id.substring(0,8)}`,"",` Tunnel: ${Q.tunnelUrl}`,` Permissions: ${Q.permissions.join(",")}`,` Added: ${Q.addedAt}`,` Last reachable: ${Q.lastReachable??"never"}`,` Workspace: ${Q.workspaceId??"-"}`,` Agent record: ${Q.agentRecordId??"-"}`];return{id:Q.id,label:Q.label,hint:Q.lastReachable?"reachable":"never",detail:z.join(`
213
- `)}});await e({title:`vibe network \u2014 ${X.length} peer(s)`,rows:H})},json:(X)=>X.map(y0)})}catch(Z){V(Z.message)}}),q.command("add <id>").description("Manually add a peer (use deploy for the SSH-install flow)").requiredOption("--label <label>","Friendly name").requiredOption("--tunnel-url <url>","Peer's tunnel URL").requiredOption("--api-key <key>","Scoped API key the peer minted for us").option("--permissions <list>",`Comma-separated permissions (default: tunnel:read). Allowed: ${E$.join(",")}`,"tunnel:read").option("--agent-record-id <id>","Platform-side agent ID for backend rotation lookup").option("--workspace-id <id>","Platform-side workspace ID").option("--json","Emit JSON result").action(($,Z)=>{try{let X={...Y.opts(),...Z},H=B2(Z.permissions);if(z0({id:$,label:Z.label,tunnelUrl:Z.tunnelUrl,apiKey:Z.apiKey,permissions:H,addedAt:new Date().toISOString(),agentRecordId:Z.agentRecordId,workspaceId:Z.workspaceId}),B(X,{ok:!0,id:$,label:Z.label,permissions:H}))return;U(`Added peer ${$} (${Z.label})`)}catch(X){V(X.message)}}),q.command("remove <id>").description("Remove a peer record (does not revoke the key on the peer)").option("--json","Emit JSON result").action(($,Z)=>{let X={...Y.opts(),...Z},H=_2($);if(B(X,{ok:H,id:$}))return;if(H)U(`Removed peer ${$}`);else V(`No peer with id ${$}`)}),q.command("update <id>").description("Modify permissions or label of an existing peer").option("--label <label>","Update friendly name").option("--permissions <list>",`Comma-separated permissions. Allowed: ${E$.join(",")}`).option("--json","Emit JSON result").action(($,Z)=>{try{let X={...Y.opts(),...Z},H={};if(Z.label)H.label=Z.label;if(Z.permissions)H.permissions=B2(Z.permissions);let Q=I2($,H);if(!Q){if(B(X,{ok:!1,id:$,error:"not_found"}))return;V(`No peer with id ${$}`);return}if(B(X,{ok:!0,id:$,peer:y0(Q)}))return;U(`Updated peer ${$}`)}catch(X){V(X.message)}}),q.command("test <id>").description("Probe a peer (calls /api/agent/identity over its tunnel)").option("--json","Emit JSON").option("--plain","Force plain text output").action(async($,Z)=>{let X={...Y.opts(),...Z},H=U2($);if(!H){if(B(X,{ok:!1,id:$,error:"not_found"}))return;V(`No peer with id ${$}`);return}try{await b({mode:f(X),fetchData:async()=>({peer:H,result:await W0($,"/api/profiles/default/agent/identity",{operation:"network-test"})}),plain:({peer:Q,result:z})=>{if(T(`Probing peer ${Q.label} (${Q.id})`),J(),z.ok){if(U(`Peer is reachable${z.rotated?" (recovered via backend rotation lookup)":""}`),z.data)console.log(JSON.stringify(z.data,null,2))}else V(`Peer call failed (${z.status}): ${z.error??"(no detail)"}`)},interactive:async({peer:Q,result:z})=>{let L=[` Peer: ${Q.label} (${Q.id})`,` Tunnel: ${Q.tunnelUrl}`,` Status: ${z.ok?"reachable":`failed (${z.status})`}`,` Rotated: ${z.rotated?"yes":"no"}`,` Error: ${z.error??"-"}`,"",` Identity: ${z.data?JSON.stringify(z.data,null,2):"-"}`];await v$({title:`Probe ${Q.label}`,body:L.join(`
214
- `)})},json:({peer:Q,result:z})=>({peer:y0(Q),result:a({ok:z.ok,status:z.status,rotated:z.rotated??!1,error:z.error??null,data:z.data??null})})})}catch(Q){V(Q.message)}})}import{existsSync as T3}from"fs";function i$(Y){return T3(F2(Y))}function D2(Y){let q=Y.command("profile").description("Manage gateway-environment profiles");q.command("list").description("List all profiles and mark the active one").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){try{let Z={...Y.opts(),...$},X=()=>{let H=f$(),z=T2().map((L)=>{let I=V0(L);return{name:L,active:L===H,globalGatewayUrl:I.globalGatewayUrl??null,workspaceGatewayUrl:I.workspaceGatewayUrl??null}});return{active:H,profiles:z}};await b({mode:f(Z),fetchData:X,plain:(H)=>{if(H.profiles.length===0){W("No profiles yet. Run 'vibe profile seed' to create the default profile.");return}T("Profiles"),n(H.profiles.map((Q)=>({Name:Q.name,Active:Q.active?K.green("\u25CF"):"","Global Gateway":Q.globalGatewayUrl??K.dim("(unset)"),"Workspace Gateway":Q.workspaceGatewayUrl??K.dim("(unset)")})))},interactive:async(H)=>{if(H.profiles.length===0){T("Profiles"),J(),W("No profiles yet. Run 'vibe profile seed' to create the default profile.");return}let Q=H.profiles.map((z)=>{let L=[`${K.bold(z.name)}${z.active?" "+K.green("\u25CF active"):""}`,"",` Global gateway: ${z.globalGatewayUrl??K.dim("(unset)")}`,` Workspace gateway: ${z.workspaceGatewayUrl??K.dim("(unset)")}`];return{id:z.name,label:z.name,hint:z.active?"active":"",detail:L.join(`
215
- `)}});await e({title:`vibe profile \u2014 ${H.profiles.length} profile(s)`,rows:Q,footer:"\u2191/\u2193 navigate \xB7 q to quit"})},json:(H)=>H})}catch(Z){V(Z.message)}}),q.command("current").description("Print the active profile name").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){try{let Z={...Y.opts(),...$};await b({mode:f(Z),fetchData:()=>({active:f$()}),plain:(X)=>{console.log(X.active)},json:(X)=>X})}catch(Z){V(Z.message)}}),q.command("show [name]").description("Print a profile's config as JSON (apiKey + secrets redacted)").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($,Z){try{let X={...Y.opts(),...Z},H=$?y$($):f$();if(!i$(H)){V(`No profile named '${H}'. Try 'vibe profile list'.`);return}let Q=()=>({name:H,active:H===f$(),config:V0(H)});await b({mode:f(X),fetchData:Q,plain:(z)=>{T(`Profile: ${z.name}`),_("Active",z.active?"yes":"no"),J(),console.log(JSON.stringify(a(z.config),null,2))},interactive:async(z)=>{let L=[`Active: ${z.active?"yes":"no"}`,"",JSON.stringify(a(z.config),null,2)].join(`
216
- `);await v$({title:`Profile: ${z.name}`,body:L,footer:"q / Esc to quit"})},json:(z)=>({name:z.name,active:z.active,config:a(z.config)})})}catch(X){V(X.message)}}),q.command("create <name>").description("Create a new profile (blank, or copied from another)").option("--from <existing>","Copy gateway URLs + config from an existing profile").option("--use","After creating, set this profile as active",!1).option("--json","Emit JSON result").action(($,Z)=>{try{let X={...Y.opts(),...Z},H=y$($);if(i$(H)){V(`Profile '${H}' already exists.`);return}let Q;if(Z.from){let z=y$(Z.from);if(!i$(z)){V(`--from: profile '${z}' does not exist.`);return}let L=V0(z);delete L["static-api-key"],delete L.agentRecordId,delete L.apiKeys,Q=L}else if(H in G2)Q=E2(H);else if(H in f0){let z=f0[H];Q={schemaVersion:void 0,globalGatewayUrl:z.globalGatewayUrl,workspaceGatewayUrl:z.workspaceGatewayUrl}}else Q={};if(R2(H,Q),Z.use)P0(H);if(B(X,{ok:!0,action:"create",profile:H,from:Z.from??null,globalGatewayUrl:Q.globalGatewayUrl??null,workspaceGatewayUrl:Q.workspaceGatewayUrl??null,active:Z.use===!0}))return;if(U(`Profile '${H}' created.`),Q.globalGatewayUrl)_("Global gateway",Q.globalGatewayUrl);if(Q.workspaceGatewayUrl)_("Workspace gateway",Q.workspaceGatewayUrl);if(Z.use)W(`Active profile is now '${H}'.`);else J(),W(`Activate with: ${K.bold(`vibe profile use ${H}`)}`)}catch(X){V(X.message)}}),q.command("use <name>").description("Set the active profile pointer").option("--json","Emit JSON result").action(($,Z)=>{try{let X={...Y.opts(),...Z},H=y$($);if(!i$(H)){V(`No profile named '${H}'. Create it with 'vibe profile create ${H}' first.`);return}if(P0(H),B(X,{ok:!0,action:"use",profile:H}))return;U(`Active profile is now '${H}'.`)}catch(X){V(X.message)}}),q.command("delete <name>").description("Delete a profile (refuses if it is the active one)").option("--confirm","Required -- destructive",!1).option("--json","Emit JSON result").action(($,Z)=>{try{let X={...Y.opts(),...Z},H=y$($);if(!Z.confirm){V(`Pass --confirm to delete profile '${H}' (this removes its config + secrets).`);return}if(!i$(H)){V(`No profile named '${H}'.`);return}if(H===f$()){V(`Cannot delete the active profile '${H}'. Switch first: 'vibe profile use <other>'.`);return}let Q=j2(H);if(B(X,{ok:Q,action:"delete",profile:H}))return;if(Q)U(`Deleted profile '${H}'.`);else V(`Profile '${H}' could not be removed.`)}catch(X){V(X.message)}}),q.command("seed").description("Idempotently create local/alpha/prod profiles").option("--json","Emit JSON result").action(($)=>{try{let Z={...Y.opts(),...$},X=N2();if(B(Z,{ok:!0,action:"seed",created:X.created,activeWritten:X.activeWritten??null}))return;if(X.created.length>0)U(`Created profile(s): ${X.created.join(", ")}`);if(X.activeWritten)W(`Active profile set to '${X.activeWritten}'.`);if(X.created.length===0&&!X.activeWritten)W("Nothing to do -- profiles already initialized.")}catch(Z){V(Z.message)}})}function x2(Y){let q=Y.command("daemon-profile").description("Manage the running daemon's in-process ProfileRegistry (distinct from `vibe profile`, which manages gateway-environment profiles on disk).");q.command("list").description("List profiles known to the running daemon").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){let Z={...Y.opts(),...$};try{await b({mode:f(Z),fetchData:()=>y(M(Z),"/api/profiles"),plain:(X)=>{if(T("Daemon Profiles"),J(),!X||X.length===0){W("No profiles attached.");return}let H=X.map((Q)=>({Name:Q.name,Default:Q.isDefault?"yes":"",Attached:Q.attached?"yes":"",BootState:Q.bootState??"-",Running:Q.isRunning?"yes":"",Port:Q.port??"-",PID:Q.pid??"-"}));n(H)}})}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(`Failed to list daemon profiles: ${C(X)}`)}}),q.command("create <name>").description("Create a new profile and attach it to the running daemon").option("--copy-from <source>","Copy config from an existing profile").option("--start","Spawn an out-of-process daemon for the new profile").option("--port <port>","Port for the spawned daemon (with --start)").option("--json","Emit JSON").action(async function($,Z){let X={...Y.opts(),...Z};try{let H={name:$};if(Z.copyFrom)H.copyFrom=Z.copyFrom;if(Z.start)H.start=!0;if(Z.port)H.port=parseInt(Z.port,10);let Q=await m(M(X),"/api/profiles",H);if(B(X,Q))return;if(U(`Profile '${$}' created.`),_("Default",Q.isDefault?"yes":"no"),_("Attached",Q.attached?"yes":"no"),Q.bootState)_("BootState",Q.bootState)}catch(H){if(X.json){B(X,{ok:!1,error:C(H)});return}V(`Failed to create profile: ${C(H)}`)}}),q.command("delete <name>").alias("rm").description("Delete a profile from the running daemon").option("--purge","Also remove the on-disk dataDir (destructive)").option("--json","Emit JSON").action(async function($,Z){let X={...Y.opts(),...Z};try{let H=Z.purge?`/api/profiles/${encodeURIComponent($)}?purge=true`:`/api/profiles/${encodeURIComponent($)}`,Q=await P$(M(X),H);if(B(X,Q))return;U(`Profile '${$}' deleted.`)}catch(H){if(X.json){B(X,{ok:!1,error:C(H)});return}V(`Failed to delete profile: ${C(H)}`)}}),q.command("start <name>").description("Ensure the profile is attached + running (idempotent)").option("--port <port>","Port for the spawned daemon").option("--json","Emit JSON").action(async function($,Z){let X={...Y.opts(),...Z};try{let H={};if(Z.port)H.port=parseInt(Z.port,10);let Q=await m(M(X),`/api/profiles/${encodeURIComponent($)}/start`,H);if(B(X,Q))return;if(U(`Profile '${$}' started.`),Q.bootState)_("BootState",Q.bootState);if(Q.port)_("Port",String(Q.port))}catch(H){if(X.json){B(X,{ok:!1,error:C(H)});return}V(`Failed to start profile: ${C(H)}`)}}),q.command("stop <name>").description("Stop the profile (detach from registry, preserve dataDir)").option("--json","Emit JSON").action(async function($,Z){let X={...Y.opts(),...Z};try{let H=await m(M(X),`/api/profiles/${encodeURIComponent($)}/stop`);if(B(X,H))return;U(`Profile '${$}' stopped.`)}catch(H){if(X.json){B(X,{ok:!1,error:C(H)});return}V(`Failed to stop profile: ${C(H)}`)}}),q.command("restart <name>").description("Stop then start the profile").option("--port <port>","Port for the spawned daemon").option("--json","Emit JSON").action(async function($,Z){let X={...Y.opts(),...Z};try{await m(M(X),`/api/profiles/${encodeURIComponent($)}/stop`);let H={};if(Z.port)H.port=parseInt(Z.port,10);let Q=await m(M(X),`/api/profiles/${encodeURIComponent($)}/start`,H);if(B(X,Q))return;if(U(`Profile '${$}' restarted.`),Q.bootState)_("BootState",Q.bootState)}catch(H){if(X.json){B(X,{ok:!1,error:C(H)});return}V(`Failed to restart profile: ${C(H)}`)}}),q.command("stats").description("Per-profile resource attribution (childPidCount, status, dataDir; CPU/heap reported at the process level)").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){let Z={...Y.opts(),...$};try{await b({mode:f(Z),fetchData:()=>y(M(Z),"/api/profile-stats"),plain:(X)=>{if(T("Profile Stats"),J(),_("PID",String(X.process.pid)),_("Uptime (s)",String(Math.round(X.process.uptimeSeconds))),_("CPU user (ms)",String(Math.round(X.process.cpuUserMs))),_("CPU system (ms)",String(Math.round(X.process.cpuSystemMs))),_("Heap used (MB)",String(Math.round(X.process.heapUsedBytes/1048576))),J(),!X.profiles||X.profiles.length===0){W("No profiles attached.");return}n(X.profiles.map((H)=>({Name:H.name,Status:H.status,ChildPids:String(H.childPidCount),DataDir:H.dataDir})))}})}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(`Failed to fetch profile stats: ${C(X)}`)}})}import b$ from"os";function R3(){return crypto.randomUUID()}function j3(){let Y=new Uint8Array(32);return crypto.getRandomValues(Y),`vcak_${Buffer.from(Y).toString("base64url")}`}function E3(){let Y=new Bun.CryptoHasher("sha256");return Y.update(`${b$.hostname()}-${b$.platform()}-${b$.arch()}`),Y.digest("hex").substring(0,16)}function N3(Y){if(!Y)return;let q=/^(\d+)([smhdw]?)$/.exec(Y.trim());if(!q)throw Error(`Invalid --expires-in: ${Y}`);let $=Number(q[1]),Z=q[2]||"d",X=Z==="s"?$*1000:Z==="m"?$*60000:Z==="h"?$*3600000:Z==="w"?$*7*86400000:$*86400000;return new Date(Date.now()+X).toISOString()}function A2(Y){Y.command("peer-bootstrap").description("Mint a peer credential bundle (used by `vibe deploy` post-install handshake)").option("--label <label>","Friendly name for the caller (logged on this host)","peer").option("--scope <list>",`Comma-separated permissions for the minted key (default: tunnel:read). Allowed: ${E$.join(",")}`,"tunnel:read").option("--expires-in <duration>","TTL for the minted key (e.g. 7d, 12h). Omit for no expiry.").option("--emit-default-key","Include this agent's FULL default API key in the bundle. Only used by `vibe deploy` over the trusted SSH channel to onboard the new agent to the backend (fresh OAuth app). Never expose this output otherwise.",!1).option("--no-output","Don't print the JSON bundle (for testing)").option("--json","Emit JSON bundle (default behaviour, kept for parity)").action(async function(q){try{let $=q.scope.split(",").map((R)=>R.trim()).filter(Boolean),Z=K0($);if(Z.length===0)throw Error(`No valid permissions in --scope. Allowed: ${E$.join(",")}`);let X=N3(q.expiresIn),H=R3(),Q=j3(),z=Z.includes("mesh:forward")?["read","mesh:forward"]:["read"],I=[...q$().apiKeys??[],{id:H,name:`peer:${q.label}`,key:Q,scopes:z,expiresAt:X,createdAt:new Date().toISOString()}];U$({apiKeys:I});let O=q$(),G=await M2(),x={id:E3(),hostname:b$.hostname(),platform:b$.platform(),arch:b$.arch(),tunnelUrl:w2()||J$()?.url||null,apiKey:Q,keyId:H,permissions:Z,expiresAt:X??null,defaultApiKey:G.substring(0,8)+"****",...q.emitDefaultKey?{fullDefaultApiKey:G}:{},agentRecordId:O.agentRecordId??null,workspaceId:O.workspaceId??null};if(q.output===!1)return;console.log(`VIBE_BOOTSTRAP_JSON=${JSON.stringify(x)}`);let F={...Y.opts(),...q};if(B(F,x))return;console.log(JSON.stringify(x,null,2))}catch($){console.error(JSON.stringify({error:$ instanceof Error?C($):String($)})),process.exit(1)}})}var D3=[{title:"Lifecycle",commands:["start","stop","restart","kill","list","status"]},{title:"Setup",commands:["setup","autostart","deploy","update","completion"]},{title:"Profile",commands:["profile"]},{title:"Plugins",commands:["plugin"]},{title:"Network",commands:["tunnel","network","peer-bootstrap","gateway-auth","url"]},{title:"Data",commands:["export","import","file","project","session","task","bookmark","state","git","key","config"]},{title:"Diagnostics",commands:["doctor","diagnostics","health","info","system","log","logs","log-level","notify"]},{title:"Maintenance",commands:["gc","nuke"]},{title:"Help",commands:["help"]}];function k0(Y){let q=new Map;for(let $ of Y.commands){if($._hidden)continue;let Z=$.name();q.set(Z,{name:Z,description:$.description()||"",cmd:$})}return q}function x3(Y,q){let $=Y;for(let Z of q){let X=$.commands.find((H)=>H.name()===Z||H.aliases().includes(Z));if(!X)return null;$=X}return $}function u0(Y){let q=new Set,$=[];for(let X of D3)for(let H of X.commands){let Q=Y.get(H);if(!Q)continue;q.add(H),$.push({group:X.title,entry:Q})}let Z=[...Y.values()].filter((X)=>!q.has(X.name));for(let X of Z.sort((H,Q)=>H.name.localeCompare(Q.name)))$.push({group:"Other",entry:X});return $}function M3(Y,q=!1){let $=k0(Y),Z=u0($),X=Z.length>0?Math.max(...Z.map((L)=>L.entry.name.length)):0,H=[];H.push(""),H.push(`${K.bold("vibe")} ${K.dim("\u2014 VibeControls Agent CLI")}`),H.push(""),H.push(`Usage: ${K.bold("vibe")} <command> [options]`),H.push(` ${K.bold("vibe help")} <command>`);let Q="";for(let{group:L,entry:I}of Z){if(L!==Q)H.push(""),H.push(K.cyan(L)),Q=L;let O=" ".repeat(X-I.name.length+2);H.push(` ${K.bold(I.name)}${O}${I.description}`)}H.push(""),H.push(K.dim("Tip: pipe to a TTY to launch the interactive browser, or run `vibe help <command>` for full options.")),H.push("");let z=H.join(`
217
- `);return q?b0(z):z}function w3(Y){let q=k0(Y);return{commands:u0(q).map(({group:Z,entry:X})=>({name:X.name,description:X.description,group:Z}))}}function S2(Y,q=!1){process.stdout.write(M3(Y,q))}function h2(Y){process.stdout.write(Y.helpInformation())}async function A3(Y){let q;try{q=await import("./index-scsjyj4m.js")}catch{return!1}let{createCliRenderer:$,BoxRenderable:Z,TextRenderable:X,SelectRenderable:H,SelectRenderableEvents:Q}=q,z=k0(Y),L=u0(z);if(L.length===0)return!1;let I=await $({exitOnCtrlC:!0,targetFps:30}),O=[],G="";for(let v of L){if(v.group!==G)O.push({kind:"header",title:v.group}),G=v.group;O.push({kind:"cmd",entry:v.entry})}let x=O.map((v,P)=>v.kind==="header"?{name:`\u2500\u2500 ${v.title} \u2500\u2500`,description:"",value:P}:{name:v.entry.name,description:v.entry.description,value:P}),F=I.root.ctx,R=new Z(F,{width:"100%",height:"100%",flexDirection:"column",backgroundColor:"#0b0d12"}),E=new X(F,{content:" vibe \u2014 command browser \u2191/\u2193 navigate \xB7 Enter view \xB7 q quit",fg:"#8be9fd",height:1}),w=new Z(F,{width:"100%",flexGrow:1,flexDirection:"row"}),D=new H(F,{width:28,height:"100%",options:x,selectedIndex:O.findIndex((v)=>v.kind==="cmd"),showDescription:!1,backgroundColor:"#0b0d12",textColor:"#cdd6f4",focusedBackgroundColor:"#0b0d12",focusedTextColor:"#cdd6f4",selectedBackgroundColor:"#1f2335",selectedTextColor:"#a6e3a1",showScrollIndicator:!0,wrapSelection:!1}),A=new Z(F,{flexGrow:1,height:"100%",flexDirection:"column",paddingLeft:2,paddingRight:2,backgroundColor:"#11141c"}),s=new X(F,{content:"",fg:"#cdd6f4"});A.add(s),w.add(D),w.add(A),R.add(E),R.add(w),I.root.add(R),D.focus();let p=(v)=>{let P=O[v];if(!P)return;if(P.kind==="header"){s.content=`
218
- ${P.title}
219
- `;return}let c=P.entry.cmd.helpInformation();s.content=`
208
+ `).filter(Boolean).length} process(es)`,detail:Y.processes||"(none found)"}),q}function l1(Y){Y.command("diagnostics").alias("diag").description("Collect a redacted diagnostic dump for support").option("--agent-url <url>","Agent URL (default http://localhost:3005)","http://localhost:3005").option("--lines <n>","Tail this many log lines","1000").option("--out <path>","Write JSON dump to file").option("--json","Emit JSON to stdout").option("--plain","Force plain text output").action(async function(q){try{let $={...Y.opts(),...q},Z=w($),X=encodeURIComponent(A($)),H=Number.parseInt($.lines??"1000",10)||1000;await P({mode:f($),fetchData:async()=>{let[Q,z,V]=await Promise.all([S6(Z,X),h6(Z,X),v6(Z)]),_=Y$(),O=a(_),F=n$(Q$(),"logs"),R=["default.log","agent.log"].map((N)=>n$(F,N)).find((N)=>g1(N))??n$(F,"default.log"),G=y6(R,H),x={timestamp:new Date().toISOString(),agent:{version:z,agentUrl:Z},system:Q,health:V,config:O,processes:f6(),logFile:R,logsTail:G},M=P6(x);return{dump:x,probes:M}},plain:(Q)=>{T("VibeControls Agent Diagnostics"),J(),W("Collecting agent state\u2026");let z=$.out?$.out:n$(x6(n$(A6(),"vibe-diag-")),`vibe-diagnostics-${Date.now()}.json`);w6(z,JSON.stringify(Q.dump,null,2),"utf8"),I("Wrote",K.bold(z)),I("Log lines",String(Q.dump.logsTail.length)),I("Processes",String(Q.dump.processes.split(`
209
+ `).filter(Boolean).length)),J(),U("Diagnostics complete. Attach the JSON to your support ticket.")},interactive:async(Q)=>{let z=Q.probes.map((_,O)=>({id:`${O}-${_.name}`,label:_.name,hint:_.ok?"ok":"fail",detail:[`${_.ok?K.green("\u2714 ok"):K.red("\u2718 fail")} ${K.bold(_.name)}`,"",_.message,..._.detail?["",_.detail]:[]].join(`
210
+ `)})),V=Q.probes.filter((_)=>_.ok).length;await r({title:`Vibe Diagnostics \u2014 ${V}/${Q.probes.length} ok`,rows:z,footer:"\u2191/\u2193 navigate \xB7 q to quit"})},json:(Q)=>({checks:Q.probes.map((z)=>({name:z.name,ok:z.ok,message:z.message})),dump:Q.dump})})}catch($){L(`Diagnostics failed: ${$ instanceof Error?C($):String($)}`)}})}import{existsSync as h$,readFileSync as m6,readdirSync as g6,renameSync as l6,rmSync as S0,statSync as n6,writeFileSync as i6}from"fs";import{join as i}from"path";import{existsSync as j$,readdirSync as b6,rmSync as k6,statSync as u6}from"fs";import{dirname as H0,join as z$}from"path";var R$="@vibecontrols";function c6(){let q=l().npmGlobalBin();if(!q)return null;let $=z$(H0(q),"lib","node_modules");if(j$($))return $;let Z=z$(H0(q),"node_modules");if(j$(Z))return Z;let X=z$(H0(q),"..","node_modules");if(j$(X))return X;return null}function d6(){let Y=l(),q=Y.bunGlobalBin();if(q){let $=z$(H0(q),"node_modules");if(j$($))return $;let Z=z$(Y.homeDir,".bun","install","global","node_modules");if(j$(Z))return Z}return null}function n1(Y){let q=z$(Y,R$);if(!j$(q))return[];try{return b6(q).filter(($)=>{if($.startsWith("."))return!1;try{return u6(z$(q,$)).isDirectory()}catch{return!1}})}catch{return[]}}function i1(){let Y=[],q=d6();if(q)for(let Z of n1(q))Y.push({packageName:`${R$}/${Z}`,root:"bun",rootDir:z$(q,R$)});let $=c6();if($)for(let Z of n1($))Y.push({packageName:`${R$}/${Z}`,root:"npm",rootDir:z$($,R$)});return Y}function p1(Y,q){if(q.dryRun)return{packageName:Y.packageName,root:Y.root,ok:!0,via:"skip"};let $=l();if(Y.root==="bun"){let X=$.platform==="win32"?"bun.exe":"bun";try{if(Bun.spawnSync([X,"remove","-g",Y.packageName],{timeout:60000,stdout:"pipe",stderr:"pipe"}).exitCode===0)return{packageName:Y.packageName,root:Y.root,ok:!0,via:"bun"}}catch{}}else{let X=$.platform==="win32"?"npm.cmd":"npm";try{if(Bun.spawnSync([X,"uninstall","-g",Y.packageName],{timeout:120000,stdout:"pipe",stderr:"pipe"}).exitCode===0)return{packageName:Y.packageName,root:Y.root,ok:!0,via:"npm"}}catch{}}let Z=z$(Y.rootDir,Y.packageName.slice(R$.length+1));try{if(j$(Z))k6(Z,{recursive:!0,force:!0});return{packageName:Y.packageName,root:Y.root,ok:!0,via:"rm"}}catch(X){return{packageName:Y.packageName,root:Y.root,ok:!1,via:"rm",error:X instanceof Error?X.message:String(X)}}}var w0=`${R$}/agent`;function o1(Y){return Y===w0}var p6=new Set(["db","plugins-registry","logs","binaries","subprocs"]);function o6(Y){let q=new Set,$=[];if(!Y)return{keep:q,unknown:$};for(let Z of Y.split(",").map((X)=>X.trim()).filter(Boolean))if(p6.has(Z))q.add(Z);else $.push(Z);return{keep:q,unknown:$}}var a6=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function t6(Y,q){if(!a6.test(q))return!1;let $=i(Y,q);try{return n6($).isDirectory()}catch{return!1}}function s6(){let Y=V$();if(!h$(Y))return[];return g6(Y).filter((q)=>t6(Y,q)).map((q)=>({profile:q,agentDir:i(Y,q)}))}function r6(){let Y=process.env.VIBECONTROLS_PROFILE||"default";return{profile:Y,agentDir:i(V$(),Y)}}function e6(Y){if(!Y)return[];return Y.split(",").map((q)=>q.trim()).filter(Boolean)}function $3(Y){let q=[],$=[],Z=[];for(let X of Y){let H=s1(X);if(!H){$.push(X);continue}let Q={packageName:H.packageName,pluginName:H.pluginName,isCore:!!H.isCore,raw:X};if(Q.isCore)Z.push(Q);else q.push(Q)}return{resolved:q,unknown:$,bundled:Z}}async function Y3(){return(await import("./subprocess-1nna3d3x.js")).killAllTracked()}function q3(Y,q){let $=J$(Y);if(!$||typeof $.pid!=="number"||$.pid<=0)return{killed:0,skipped:0};let Z=l();if(!Z.isProcessAlive($.pid)){if(!q)X$(Y);return{killed:0,skipped:1}}if(q)return W(` would kill tunnel pid ${$.pid} (${$.provider}) from ${K.dim(Y)}`),{killed:1,skipped:0};let X=Z.killProcessTree($.pid,"SIGTERM");if(X&&Z.isProcessAlive($.pid))Z.killProcessTree($.pid,"SIGKILL");return X$(Y),{killed:X?1:0,skipped:X?0:1}}function e1(){return i(l().homeDir,".bun","install","global")}function $2(Y,q){let $=e1(),Z=i($,"package.json"),X=i($,"bun.lock");if(!h$(Z))return{droppedCount:0,manifestPath:Z,lockPath:X};let H=typeof Y==="function"?Y:(D)=>D===Y,Q;try{Q=m6(Z,"utf8")}catch{return{droppedCount:0,manifestPath:Z,lockPath:X}}let z;try{z=JSON.parse(Q)}catch{return{droppedCount:0,manifestPath:Z,lockPath:X}}if(!z.dependencies||typeof z.dependencies!=="object")return{droppedCount:0,manifestPath:Z,lockPath:X};let V=Object.keys(z.dependencies),_={};for(let D of V)if(!H(D))_[D]=z.dependencies[D];let O=V.length-Object.keys(_).length;if(O===0)return{droppedCount:0,manifestPath:Z,lockPath:X};if(q)return W(` would drop ${O} dep(s) from ${K.dim(Z)} and remove ${K.dim(X)}`),{droppedCount:O,manifestPath:Z,lockPath:X};z.dependencies=_;let F=`${Z}.${process.pid}.tmp`;if(i6(F,`${JSON.stringify(z,null,2)}
211
+ `,{encoding:"utf8"}),l6(F,Z),h$(X))try{S0(X,{force:!0})}catch{}return{droppedCount:O,manifestPath:Z,lockPath:X}}async function _$(Y,q){if(!h$(Y))return;if(q){W(` would remove ${K.dim(Y)}`);return}try{S0(Y,{recursive:!0,force:!0})}catch($){j(`Failed to remove ${Y}: ${$ instanceof Error?C($):String($)}`)}}async function Z3(Y,q,$){if(q)return W(` would uninstall plugin ${K.bold(Y)}`),!0;if($)try{if((await fetch(`${$}/api/plugins/remove`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({packageName:Y})})).ok)return!0}catch{}try{let H=l(),Q=H.which("bun")??`bun${H.executableSuffix}`;if(Bun.spawnSync([Q,"remove","-g",Y],{timeout:60000,stdout:"pipe",stderr:"pipe"}).exitCode===0)return!0}catch{}let Z=i(e1(),"node_modules",Y),X=!1;try{if(h$(Z))S0(Z,{recursive:!0,force:!0}),X=!0}catch{}$2(Y,!1);try{let{pruneStaleBunBinShims:H}=await import("./prune-stale-shims-23y0stm8.js");H()}catch{}return X||!0}async function X3(Y,q){try{let $=await fetch(`${Y}/api/plugins/prereqs/uninstall`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({packageName:q})});if(!$.ok)return{ok:!1,pendingSudo:[]};let Z=await $.json();return{ok:!!Z.ok,pendingSudo:Z.pendingSudo??[]}}catch{return{ok:!1,pendingSudo:[]}}}async function H3(Y,q,$){try{let Z=await fetch(`${Y}/api/plugins/nuke`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(q?{packageName:q,dryRun:$}:{dryRun:$})});if(!Z.ok)return[];let X=await Z.json(),H=[];for(let Q of X.results??[]){if(Q.error){H.push(`${Q.plugin} (failed: ${Q.error})`);continue}for(let z of Q.reaped??[])H.push(`${Q.plugin}: ${z}`)}return H}catch{return[]}}async function Q3(Y,q){T(`Nuking agent: ${Y.profile}`),I("Path",Y.agentDir);let $=null;try{let X=(await q.serviceManager.listInstances()).find((H)=>H.name===Y.profile);if(X?.status==="running"){if($=`http://localhost:${X.config?.port??3005}`,(!q.keep.has("binaries")||!q.keep.has("subprocs"))&&(q.nukeAllPlugins||q.removePlugins.length>0)){let z=q.nukeAllPlugins?[void 0]:q.removePlugins.map((V)=>V.packageName);for(let V of z){let _=await H3($,V,q.dryRun);for(let O of _)if(q.dryRun)W(` would nuke \u2192 ${O}`);else U(`Plugin nuke \u2192 ${O}`)}}if(q.dryRun)W(` would stop running agent ${K.bold(Y.profile)}`);else try{await q.serviceManager.stop(Y.profile),U(`Stopped ${K.bold(Y.profile)}`)}catch(z){j(`Failed to stop ${Y.profile}: ${z}`)}}}catch{}if(!q.dryRun&&!q.keep.has("subprocs"))try{let{reaped:X}=await Y3();if(X>0)U(`Reaped ${X} tracked subprocess(es)`)}catch{}else if(q.keep.has("subprocs"))W(" keeping tracked subprocesses (--keep includes subprocs)");if(!q.keep.has("subprocs"))try{let{killed:X}=q3(Y.agentDir,q.dryRun);if(X>0&&!q.dryRun)U(`Killed persisted tunnel subprocess for ${Y.profile}`)}catch(X){j(`Failed to kill tunnel for ${Y.profile}: ${X instanceof Error?C(X):String(X)}`)}let Z=[];if(!q.keep.has("binaries")){let X=r1(Y.agentDir),H=new Map;for(let Q of X){let z=H.get(Q.pluginPackageName)??[];z.push(Q),H.set(Q.pluginPackageName,z)}if(H.size===0)W(" no agent-installed prerequisites tracked");else if(!$)j(` agent not running \u2014 cannot call prereqs/uninstall on ${H.size} plugin(s); rerun with the agent up to clean binaries`);else for(let[Q,z]of H){if(q.dryRun){W(` would call prereqs/uninstall on ${K.bold(Q)} (${z.length} item(s))`);continue}let V=await X3($,Q);if(V.ok)U(`Uninstalled prereqs for ${Q}`);else j(`Plugin ${Q} did not implement prereqs/uninstall`);for(let _ of V.pendingSudo)Z.push(_)}}else W(" keeping installed binaries (--keep includes binaries)");for(let X of q.removePlugins)if(await Z3(X.packageName,q.dryRun,$))U(`Removed plugin ${X.packageName}`);else j(`Failed to remove plugin ${X.packageName}`);if(q.nukeAllPlugins||!q.keep.has("plugins-registry"))await _$(i(Y.agentDir,"agent-plugins"),q.dryRun);else W(" keeping local agent-plugins store (--keep includes plugins-registry)");if(!q.keep.has("db"))await _$(i(Y.agentDir,"agent-db"),q.dryRun);else W(" keeping encrypted DB (--keep includes db)");if(!q.keep.has("plugins-registry"))await _$(i(Y.agentDir,"plugins.json"),q.dryRun),await _$(i(Y.agentDir,"prereqs-installed.json"),q.dryRun);else W(" keeping plugins.json + prereqs-installed.json (--keep includes plugins-registry)");if(!q.keep.has("logs"))await _$(i(Y.agentDir,"logs"),q.dryRun);else W(" keeping log files (--keep includes logs)");if(q.removeConfig)await _$(i(Y.agentDir,"config.json"),q.dryRun),U(`Removed config.json for ${Y.profile}`);return{pendingSudo:Z}}function Y2(Y){Y.command("nuke").description("Cleanly remove agent state, tracked binaries, and (optionally) plugins/config across one or all agents.").option("--remove-plugins <csv>","Comma-separated plugin names (short or full) to uninstall").option("--remove-config","Also delete config.json").option("--all","Apply to every agent under .boff/vibecontrols/agents/ and wipe all external provider plugins").option("--keep <csv>","Comma-separated list of things to preserve. Valid: db, plugins-registry, logs, binaries, subprocs").option("--dry-run","Print what would happen without doing it").option("-y, --yes","Skip the confirmation prompt").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=q.all?s6():[r6()].filter((G)=>h$(G.agentDir));if(Z.length===0){W("Nothing to nuke \u2014 no agent state directories found.");return}let X=e6(q.removePlugins),{resolved:H,unknown:Q,bundled:z}=$3(X);if(Q.length>0){L(`Unknown plugin(s): ${Q.join(", ")} \u2014 try the full @vibecontrols/* package name`);return}if(z.length>0)for(let G of z)j(`Skipping ${K.bold(G.packageName)}: bundled with the agent (uninstall the agent itself with \`npm uninstall -g @vibecontrols/agent\`)`);let{keep:V,unknown:_}=o6(q.keep);if(_.length>0){L(`Unknown --keep value(s): ${_.join(", ")} \u2014 valid: db, plugins-registry, logs, binaries, subprocs`);return}if(T(q.dryRun?"Dry-run nuke":"Nuke"),W(`Agents: ${Z.map((G)=>G.profile).join(", ")}`),W(`Plugins: ${H.map((G)=>G.packageName).join(", ")||"(none)"}`),W(`Remove config: ${q.removeConfig?"yes":"no"}`),W(`Keep: ${V.size>0?[...V].sort().join(", "):"(nothing)"}`),W(`Wipe bun-global @vibecontrols/*: ${q.all?"yes":"no"}`),J(),!q.yes&&!q.dryRun){if(!await T$(K.bold("This will permanently delete the listed state. Continue?"))){W("Cancelled.");return}J()}let O=new p,F=[];for(let G of Z){let{pendingSudo:x}=await Q3(G,{serviceManager:O,removePlugins:H,nukeAllPlugins:!!q.all,removeConfig:!!q.removeConfig,keep:V,dryRun:!!q.dryRun});for(let M of x)F.push(M);J()}let D=[],R=null;if(q.all){try{if(q.dryRun){let N=await A0();R=N,W(` would clear ${N.count} secret(s) from ${N.backend}`)}else{let N=await A0(),S=!0;if(N.count>0&&!q.yes)S=await T$(K.bold(`About to remove ${N.count} secret(s) from ${N.backend}. Continue?`));if(S)if(R=await a1(),R.count>0)U(`Cleared ${R.count} secret(s) from ${R.backend}`);else W(" no secrets to clear");else W(" skipped clearing secrets (user declined)"),R={count:0,backend:"none",names:[]}}}catch(N){j(`Failed to clear secrets: ${N instanceof Error?C(N):String(N)}`)}let G=i1().filter((N)=>!o1(N.packageName));if(G.length===0)W(" no @vibecontrols/* packages found in bun-global / npm-global");else{W(` found ${G.length} @vibecontrols/* package(s) in global roots`);for(let N of G){let S=p1(N,{dryRun:!!q.dryRun});if(D.push(S),q.dryRun)W(` would uninstall ${K.bold(N.packageName)} (${N.root}-global)`);else if(S.ok)U(`Removed ${N.packageName} (${N.root}-global, via ${S.via})`);else j(`Failed to remove ${N.packageName} (${N.root}-global): ${S.error??"unknown"}`)}}let{droppedCount:x,manifestPath:M}=$2((N)=>N.startsWith("@vibecontrols/")&&N!==w0,!!q.dryRun);if(x>0&&!q.dryRun)U(`Dropped ${x} @vibecontrols/* dep(s) from ${M}`);await _$(i(Z$(),"agents.json"),!!q.dryRun),await _$(i(Z$(),".consent.json"),!!q.dryRun)}if(F.length>0){J(),j(`${F.length} command(s) require sudo to fully uninstall:`);for(let G of F)I(` ${G.name}`,G.command)}if(B($,{ok:!0,deleted:Z.map((G)=>G.profile),removedGlobalPackages:D,clearedSecrets:R,dryRun:!!q.dryRun}))return;if(q.all&&D.length>0&&!q.dryRun){let G=D.filter((x)=>x.ok).length;J(),W(`${E.info} Uninstalled ${G}/${D.length} global @vibecontrols/* package(s)`)}if(J(),U(q.dryRun?"Dry-run complete.":"Nuke complete."),q.all&&!q.dryRun)W(`${E.info} To remove the agent itself: ${K.bold("npm uninstall -g @vibecontrols/agent")} (or ${K.bold("bun remove -g @vibecontrols/agent")})`)}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}L(X)}})}import{existsSync as z3}from"fs";import{platform as W3}from"os";var K3="http://localhost:3005";function q2(Y){if(Y==="pass")return K.green("\u2714 pass");if(Y==="warn")return K.yellow("\u26A0 warn");return K.red("\u2718 fail")}async function V3(Y){try{return await y(Y,"/health"),{name:"Agent HTTP reachable",grade:"pass",message:Y}}catch(q){return{name:"Agent HTTP reachable",grade:"fail",message:C(q),hint:"Run `vibe start` (or check `vibe status` if it should already be running)."}}}async function L3(){try{let Y="default";try{Y=Y0()}catch{}let q=await Z2(`${Y}:static-api-key`),$=Y$();if(!Boolean(q||$["static-api-key"]||process.env.AGENT_API_KEY))return{name:"Agent config / API key",grade:"warn",message:"No persistent API key set; agent will mint a fresh one each restart.",hint:"Run `vibe config --set static-api-key=true` to persist."};return{name:"Agent config / API key",grade:"pass",message:"config.json present, API key persisted"}}catch(Y){return{name:"Agent config / API key",grade:"fail",message:C(Y)}}}function O3(){let Y=Q$();if(!z3(Y))return{name:"Agent working directory",grade:"warn",message:`${Y} does not exist (will be created on first start)`};return{name:"Agent working directory",grade:"pass",message:Y}}async function B3(Y,q){try{if((await y(Y,`/api/profiles/${q}/agent/gateway-auth`))?.configured)return{name:"Gateway OAuth",grade:"pass",message:"configured"};return{name:"Gateway OAuth",grade:"warn",message:"not configured \u2014 agent works locally but won't sync with platform",hint:"Add the agent on the VibeControls platform and paste the credentials."}}catch{return{name:"Gateway OAuth",grade:"warn",message:"could not query agent for gateway-auth state"}}}async function J3(Y,q){try{let $=await y(Y,`/api/profiles/${q}/plugins`),Z=$?.plugins??$??[],X=Z.filter((H)=>H.status==="error"||H.status==="failed");if(X.length>0)return{name:"Plugin registry",grade:"fail",message:`${X.length} plugin(s) failed to load`,hint:X.map((H)=>H.name??H.packageName).join(", ")};return{name:"Plugin registry",grade:"pass",message:`${Z.length} plugin(s) loaded cleanly`}}catch{return{name:"Plugin registry",grade:"warn",message:"could not query agent for plugin list"}}}function U3(){let Y=W3();if(!["linux","darwin","win32"].includes(Y))return{name:"OS runtime",grade:"warn",message:`${Y} is not officially supported (linux, darwin, win32)`};let $=typeof Bun<"u"?Bun.version:null;if(!$)return{name:"OS runtime",grade:"warn",message:`${Y} / no Bun runtime detected`};return{name:"OS runtime",grade:"pass",message:`${Y} / Bun ${$}`}}function H2(Y){Y.command("doctor").description("Run a graded health check across the agent's subsystems").option("--agent-url <url>","Agent URL",K3).option("--profile <name>","Target a specific profile by name").option("--json","Emit machine-readable JSON instead of grading text").option("--plain","Force plain text output").action(async function(q){let $={...Y.opts(),...q},Z=w($),X=encodeURIComponent(A($)),H=[];if(await P({mode:f($),fetchData:async()=>{let Q=[];Q.push(U3()),Q.push(O3()),Q.push(await L3()),Q.push(await V3(Z)),Q.push(await B3(Z,X)),Q.push(await J3(Z,X));let z=X2();for(let V of z.getDoctorChecks())try{let _=await V.run();for(let O of _){let F=O.ok?"pass":O.grade??"fail";Q.push({name:O.name,grade:F,message:O.message,hint:O.hint})}}catch(_){Q.push({name:`${V.source}: doctor contributor`,grade:"warn",message:`contributor threw: ${_.message}`})}return H=Q,Q},plain:(Q)=>{T("Vibe Doctor"),J();for(let O of Q)if(console.log(`${q2(O.grade)} ${K.bold(O.name)}`),console.log(` ${O.message}`),O.hint)console.log(` ${K.dim("\u2192 "+O.hint)}`);J();let z=Q.filter((O)=>O.grade==="fail").length,V=Q.filter((O)=>O.grade==="warn").length,_=Q.filter((O)=>O.grade==="pass").length;if(W(`${_} pass, ${V} warn, ${z} fail`),z>0)L("Doctor found problems. See hints above."),process.exitCode=1;else if(V>0)W("Doctor finished with warnings.");else U("All checks pass.")},interactive:async(Q)=>{let z=Q.map((F,D)=>{let R=[`${q2(F.grade)} ${K.bold(F.name)}`,"",F.message];if(F.hint)R.push(""),R.push(K.dim("\u2192 "+F.hint));return{id:`${D}-${F.name}`,label:F.name,hint:F.grade==="pass"?"ok":F.grade,detail:R.join(`
212
+ `)}}),V=Q.filter((F)=>F.grade==="fail").length,_=Q.filter((F)=>F.grade==="warn").length,O=Q.filter((F)=>F.grade==="pass").length;if(await r({title:`Vibe Doctor \u2014 ${O} pass, ${_} warn, ${V} fail`,rows:z,footer:"\u2191/\u2193 navigate \xB7 q to quit"}),V>0)process.exitCode=1},json:(Q)=>({checks:Q.map((z)=>({name:z.name,ok:z.grade==="pass",grade:z.grade,message:z.message,hint:z.hint??null}))})}),H.some((Q)=>Q.grade==="fail"))process.exitCode=1})}var I3="http://localhost:3005",h0=new Set(["debug","info","warn","error","silent"]);function Q2(Y){Y.command("log-level [level]").description("Show or update the running agent's log level").option("--agent-url <url>","Agent URL",I3).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function(q,$){try{let Z={...Y.opts(),...$},X=w(Z),H=encodeURIComponent(A(Z));if(!q){await P({mode:f(Z),fetchData:async()=>{return{level:(await y(X,`/api/profiles/${H}/agent/log-level`))?.level??"(unknown)"}},plain:(z)=>{T("Agent Log Level"),I("Current",z.level)},interactive:async(z)=>{await v$({title:"Agent Log Level",body:`Current: ${z.level}`,footer:"press q to exit"})}});return}let Q=q.toLowerCase();if(!h0.has(Q)){if(!B(Z,{ok:!1,error:`Invalid log level: ${q}`,valid:[...h0]}))L(`Invalid log level: ${q}. Use one of: ${[...h0].join(", ")}`);return}if(await m(X,`/api/profiles/${H}/agent/log-level`,{level:Q}),B(Z,{ok:!0,level:Q}))return;U(`Log level set to ${Q}`)}catch(Z){if(B({json:!!$.json},{ok:!1,error:C(Z)}))return;L(C(Z))}})}import{existsSync as z2,readdirSync as W2,statSync as K2,unlinkSync as _3}from"fs";import{join as v0}from"path";function C3(){let Y=V$();if(!z2(Y))return[];return W2(Y).map((q)=>v0(Y,q)).filter((q)=>K2(q).isDirectory())}function G3(Y,q,$){let Z=v0(Y,"logs");if(!z2(Z))return{count:0,bytes:0};let X=Date.now()-q*86400000,H=0,Q=0;for(let z of W2(Z)){let V=v0(Z,z),_=K2(V);if(!_.isFile())continue;if(_.mtimeMs>X)continue;if(H+=1,Q+=_.size,!$)try{_3(V)}catch{}}return{count:H,bytes:Q}}function F3(Y,q){let $=J$(Y);if(!$)return 0;if(B$($.pid))return 0;if(!q)X$(Y);return 1}function V2(Y){Y.command("gc").description("Garbage-collect stale agent state (tunnel files, old logs)").option("--keep-days <n>","Keep log files newer than N days","14").option("--dry-run","Show what would be removed without changing anything",!1).option("-y, --yes","Skip the confirmation prompt (for scripts/CI)",!1).option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};if(!q.dryRun&&!await q0($,"Remove stale agent state now?")){W("Aborted.");return}try{let Z=Number(q.keepDays);if(!Number.isFinite(Z)||Z<0){if($.json){B($,{ok:!1,error:`Invalid --keep-days: ${q.keepDays}`});return}L(`Invalid --keep-days: ${q.keepDays}`);return}let X=Boolean(q.dryRun);if(!$.json)T(X?"vibe gc (dry-run)":"vibe gc"),J();let H={staleTunnelStates:0,oldLogFiles:0,bytesFreed:0},Q=[];for(let z of C3()){let V=F3(z,X);H.staleTunnelStates+=V;let _=G3(z,Z,X);if(H.oldLogFiles+=_.count,H.bytesFreed+=_.bytes,V>0||_.count>0)Q.push(z)}if(B($,{ok:!0,removed:Q,staleTunnelStates:H.staleTunnelStates,oldLogFiles:H.oldLogFiles,freedBytes:H.bytesFreed,dryRun:X}))return;if(I("Stale tunnel state files",String(H.staleTunnelStates)),I("Old log files",String(H.oldLogFiles)),I("Bytes freed",`${(H.bytesFreed/1048576).toFixed(2)} MiB`),J(),X)W(K.dim("dry-run: no files were removed"));else U("gc complete")}catch(Z){if($.json){B($,{ok:!1,error:C(Z)});return}L(C(Z))}})}async function Q0(Y,q,$,Z){W(`\u2192 ${$}`);let X=await Y.run(q,{timeoutMs:Z});if(X.code!==0)throw j(X.stderr.slice(0,600)),Error(`${$} failed (exit ${X.code})`);return X.stdout}function O2(Y){Y.command("deploy <target>").description("Install + auto-configure the VibeControls agent on a remote target (defaults to SSH)").option("--version <version>","Pin a specific agent version (default: latest)").option("--registry <url>","npm registry (default: https://registry.npmjs.org/)").option("-i, --identity-file <path>","SSH identity file (override ssh_config)").option("--label <label>","Friendly name to record this peer under (default: target host)").option("--permissions <list>","Permissions to grant ourselves on the new peer (comma-separated)","tunnel:read,session:list,plugin:list,diagnostics:read").option("--expires-in <duration>","TTL for the minted peer key (default: no expiry)").option("--install-plugins <list>","Comma-separated plugin packages to also install on the remote agent").option("--autostart","Run `vibe autostart install` on the remote agent",!1).option("--no-bun","Skip Bun runtime install on the remote (default: best-effort)").option("--confirm","Required to proceed (no destructive ops; this is a sanity gate)").option("--json","Emit JSON").action(async function(q,$){let Z={...Y.opts(),...$};try{if(!$.confirm){L("Pass --confirm to proceed. `vibe deploy` runs npm install on the remote host.");return}let X=L2(q,{identityFile:$.identityFile});T(`vibe deploy \u2192 ${X.id}`),J(),W("Probing remote host\u2026");let H=await X.probe();if(I("Remote OS",H.os??"(unknown)"),I("Remote arch",H.arch??"(unknown)"),H.npm)I("Remote npm",H.npm);if(H.bun)I("Remote bun",H.bun);if(H.vibe)I("Remote vibe (existing)",H.vibe);if(J(),!H.bun){if($.bun===!1){L("Bun is required to run the agent but is not installed and --no-bun was passed. Install Bun manually, then re-run.");return}W("Installing Bun on remote\u2026");let M=await X.run(["sh","-c",`curl -fsSL https://bun.sh/install | bash && echo 'export PATH="$HOME/.bun/bin:$PATH"' >> ~/.bashrc`],{timeoutMs:300000});if(M.code!==0){j(M.stderr.slice(0,500)),L("Bun auto-install failed. Install Bun manually, then re-run.");return}let N=await X.run(["sh","-c","$HOME/.bun/bin/bun --version 2>/dev/null"],{timeoutMs:1e4});if(N.code===0&&N.stdout.trim())H.bun="$HOME/.bun/bin/bun",I("Remote bun (installed)",N.stdout.trim());else{L("Bun installer ran but the binary isn't reachable. Manual investigation needed.");return}}let Q=$.version??"latest",z=$.registry??"https://registry.npmjs.org/";if(!/^[A-Za-z0-9._@/^~>=<-]+$/.test(Q)){L(`Invalid agent version: ${Q}`);return}if(!/^https?:\/\/[A-Za-z0-9._~:/?#@!$&'()*+,;=%-]+$/.test(z)){L(`Invalid registry URL: ${z}`);return}await Q0(X,["sh","-c",`export PATH="$HOME/.bun/bin:$PATH"; npm_config_registry="${z}" bun install -g @vibecontrols/agent@${Q} --no-cache`],`Installing @vibecontrols/agent@${Q} via bun`,600000);let V='export PATH="$HOME/.bun/bin:$PATH"; ',_=await Q0(X,["sh","-c",`${V}vibe --version`],"Verifying remote vibe binary",15000);if(I("Remote agent version",_.trim()),$.autostart)await Q0(X,["sh","-c",`${V}vibe autostart install`],"Installing autostart unit",60000);if($.installPlugins)for(let M of $.installPlugins.split(",").map((N)=>N.trim()).filter(Boolean))await Q0(X,["sh","-c",`${V}vibe plugin install ${M}`],`Installing plugin ${M}`,300000);W("Starting remote agent in daemon mode\u2026"),await X.run(["sh","-c",`${V}vibe start`],{timeoutMs:60000}),W("Waiting for remote tunnel\u2026");let O=null,F=$.expiresIn?` --expires-in ${$.expiresIn}`:"",D=$.label??X.id,R=$.permissions??"tunnel:read";for(let M=0;M<15;M++){let N=await X.run(["sh","-c",`${V}vibe peer-bootstrap --label '${D.replace(/'/g,"")}' --scope ${R}${F} 2>/dev/null`],{timeoutMs:15000});if(N.code===0){let S=N.stdout,q$=S.indexOf("{"),o=S.lastIndexOf("}");if(q$>=0&&o>q$){let v=S.slice(q$,o+1);try{JSON.parse(v),O=v;break}catch{}}}await new Promise((S)=>setTimeout(S,2000))}if(!O){j("Could not run `vibe peer-bootstrap` on the remote. The agent is installed but not registered as a peer. Run `vibe network add ...` manually with the remote's API key + tunnel URL.");return}let G;try{G=JSON.parse(O)}catch(M){j(`Could not parse peer-bootstrap output: ${M.message}`);return}if(!G.tunnelUrl)j("Remote agent has no tunnel URL yet \u2014 it may still be coming up. Re-run `vibe network test <id>` later.");if(z0({id:G.id,label:D,tunnelUrl:G.tunnelUrl??"",apiKey:G.apiKey,permissions:G.permissions,addedAt:new Date().toISOString(),agentRecordId:G.agentRecordId??void 0,workspaceId:G.workspaceId??void 0,fingerprint:G.id}),B(Z,{ok:!0,host:q,version:_.trim(),peerId:G.id,tunnelUrl:G.tunnelUrl??null}))return;if(J(),U(`Deployed agent + registered peer ${G.id}`),I("Remote tunnel",G.tunnelUrl??"(pending)"),I("Permissions",G.permissions.join(",")),G.expiresAt)I("Key expires",G.expiresAt);J(),W(`${K.dim("Try it")}: ${K.bold(`vibe network test ${G.id.substring(0,8)}`)}`);let x=await W0(G.id,"/api/profiles/default/agent/identity",{operation:"post-deploy-probe"});if(x.ok)U("Peer probe succeeded.");else j(`Peer probe failed: ${x.status} ${x.error??""}. Tunnel may still be warming up.`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(C(X))}})}function B2(Y){let q=Y.split(",").map((Z)=>Z.trim()).filter(Boolean),$=K0(q);if($.length!==q.length)throw Error(`Invalid permission(s). Allowed: ${E$.join(",")}`);return $}function y0(Y){let{apiKey:q,...$}=Y;return a({...$,apiKey:"[REDACTED]"})}function C2(Y){let q=Y.command("network").description("Manage the mesh of peer agents this agent talks to");q.command("list").description("List configured peer agents").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){try{let Z={...Y.opts(),...$};await P({mode:f(Z),fetchData:()=>J2(),plain:(X)=>{if(X.length===0){W("No peers configured. Add one via `vibe deploy <ssh-target>` or `vibe network add`.");return}T("Peer agents"),n(X.map((H)=>({ID:H.id.substring(0,8),Label:H.label,Tunnel:H.tunnelUrl,Permissions:H.permissions.join(","),Last_Reachable:H.lastReachable??"never"})))},interactive:async(X)=>{if(X.length===0){T("Peer agents"),J(),W("No peers configured. Add one via `vibe deploy <ssh-target>` or `vibe network add`.");return}let H=X.map((Q)=>{let z=[`${K.bold(Q.label)} ${Q.id.substring(0,8)}`,"",` Tunnel: ${Q.tunnelUrl}`,` Permissions: ${Q.permissions.join(",")}`,` Added: ${Q.addedAt}`,` Last reachable: ${Q.lastReachable??"never"}`,` Workspace: ${Q.workspaceId??"-"}`,` Agent record: ${Q.agentRecordId??"-"}`];return{id:Q.id,label:Q.label,hint:Q.lastReachable?"reachable":"never",detail:z.join(`
213
+ `)}});await r({title:`vibe network \u2014 ${X.length} peer(s)`,rows:H})},json:(X)=>X.map(y0)})}catch(Z){L(Z.message)}}),q.command("add <id>").description("Manually add a peer (use deploy for the SSH-install flow)").requiredOption("--label <label>","Friendly name").requiredOption("--tunnel-url <url>","Peer's tunnel URL").requiredOption("--api-key <key>","Scoped API key the peer minted for us").option("--permissions <list>",`Comma-separated permissions (default: tunnel:read). Allowed: ${E$.join(",")}`,"tunnel:read").option("--agent-record-id <id>","Platform-side agent ID for backend rotation lookup").option("--workspace-id <id>","Platform-side workspace ID").option("--json","Emit JSON result").action(($,Z)=>{try{let X={...Y.opts(),...Z},H=B2(Z.permissions);if(z0({id:$,label:Z.label,tunnelUrl:Z.tunnelUrl,apiKey:Z.apiKey,permissions:H,addedAt:new Date().toISOString(),agentRecordId:Z.agentRecordId,workspaceId:Z.workspaceId}),B(X,{ok:!0,id:$,label:Z.label,permissions:H}))return;U(`Added peer ${$} (${Z.label})`)}catch(X){L(X.message)}}),q.command("remove <id>").description("Remove a peer record (does not revoke the key on the peer)").option("--json","Emit JSON result").action(($,Z)=>{let X={...Y.opts(),...Z},H=_2($);if(B(X,{ok:H,id:$}))return;if(H)U(`Removed peer ${$}`);else L(`No peer with id ${$}`)}),q.command("update <id>").description("Modify permissions or label of an existing peer").option("--label <label>","Update friendly name").option("--permissions <list>",`Comma-separated permissions. Allowed: ${E$.join(",")}`).option("--json","Emit JSON result").action(($,Z)=>{try{let X={...Y.opts(),...Z},H={};if(Z.label)H.label=Z.label;if(Z.permissions)H.permissions=B2(Z.permissions);let Q=I2($,H);if(!Q){if(B(X,{ok:!1,id:$,error:"not_found"}))return;L(`No peer with id ${$}`);return}if(B(X,{ok:!0,id:$,peer:y0(Q)}))return;U(`Updated peer ${$}`)}catch(X){L(X.message)}}),q.command("test <id>").description("Probe a peer (calls /api/agent/identity over its tunnel)").option("--json","Emit JSON").option("--plain","Force plain text output").action(async($,Z)=>{let X={...Y.opts(),...Z},H=U2($);if(!H){if(B(X,{ok:!1,id:$,error:"not_found"}))return;L(`No peer with id ${$}`);return}try{await P({mode:f(X),fetchData:async()=>({peer:H,result:await W0($,"/api/profiles/default/agent/identity",{operation:"network-test"})}),plain:({peer:Q,result:z})=>{if(T(`Probing peer ${Q.label} (${Q.id})`),J(),z.ok){if(U(`Peer is reachable${z.rotated?" (recovered via backend rotation lookup)":""}`),z.data)console.log(JSON.stringify(z.data,null,2))}else L(`Peer call failed (${z.status}): ${z.error??"(no detail)"}`)},interactive:async({peer:Q,result:z})=>{let V=[` Peer: ${Q.label} (${Q.id})`,` Tunnel: ${Q.tunnelUrl}`,` Status: ${z.ok?"reachable":`failed (${z.status})`}`,` Rotated: ${z.rotated?"yes":"no"}`,` Error: ${z.error??"-"}`,"",` Identity: ${z.data?JSON.stringify(z.data,null,2):"-"}`];await v$({title:`Probe ${Q.label}`,body:V.join(`
214
+ `)})},json:({peer:Q,result:z})=>({peer:y0(Q),result:a({ok:z.ok,status:z.status,rotated:z.rotated??!1,error:z.error??null,data:z.data??null})})})}catch(Q){L(Q.message)}})}import{existsSync as T3}from"fs";function i$(Y){return T3(F2(Y))}function D2(Y){let q=Y.command("profile").description("Manage gateway-environment profiles");q.command("list").description("List all profiles and mark the active one").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){try{let Z={...Y.opts(),...$},X=()=>{let H=f$(),z=T2().map((V)=>{let _=V0(V);return{name:V,active:V===H,globalGatewayUrl:_.globalGatewayUrl??null,workspaceGatewayUrl:_.workspaceGatewayUrl??null}});return{active:H,profiles:z}};await P({mode:f(Z),fetchData:X,plain:(H)=>{if(H.profiles.length===0){W("No profiles yet. Run 'vibe profile seed' to create the default profile.");return}T("Profiles"),n(H.profiles.map((Q)=>({Name:Q.name,Active:Q.active?K.green("\u25CF"):"","Global Gateway":Q.globalGatewayUrl??K.dim("(unset)"),"Workspace Gateway":Q.workspaceGatewayUrl??K.dim("(unset)")})))},interactive:async(H)=>{if(H.profiles.length===0){T("Profiles"),J(),W("No profiles yet. Run 'vibe profile seed' to create the default profile.");return}let Q=H.profiles.map((z)=>{let V=[`${K.bold(z.name)}${z.active?" "+K.green("\u25CF active"):""}`,"",` Global gateway: ${z.globalGatewayUrl??K.dim("(unset)")}`,` Workspace gateway: ${z.workspaceGatewayUrl??K.dim("(unset)")}`];return{id:z.name,label:z.name,hint:z.active?"active":"",detail:V.join(`
215
+ `)}});await r({title:`vibe profile \u2014 ${H.profiles.length} profile(s)`,rows:Q,footer:"\u2191/\u2193 navigate \xB7 q to quit"})},json:(H)=>H})}catch(Z){L(Z.message)}}),q.command("current").description("Print the active profile name").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){try{let Z={...Y.opts(),...$};await P({mode:f(Z),fetchData:()=>({active:f$()}),plain:(X)=>{console.log(X.active)},json:(X)=>X})}catch(Z){L(Z.message)}}),q.command("show [name]").description("Print a profile's config as JSON (apiKey + secrets redacted)").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($,Z){try{let X={...Y.opts(),...Z},H=$?y$($):f$();if(!i$(H)){L(`No profile named '${H}'. Try 'vibe profile list'.`);return}let Q=()=>({name:H,active:H===f$(),config:V0(H)});await P({mode:f(X),fetchData:Q,plain:(z)=>{T(`Profile: ${z.name}`),I("Active",z.active?"yes":"no"),J(),console.log(JSON.stringify(a(z.config),null,2))},interactive:async(z)=>{let V=[`Active: ${z.active?"yes":"no"}`,"",JSON.stringify(a(z.config),null,2)].join(`
216
+ `);await v$({title:`Profile: ${z.name}`,body:V,footer:"q / Esc to quit"})},json:(z)=>({name:z.name,active:z.active,config:a(z.config)})})}catch(X){L(X.message)}}),q.command("create <name>").description("Create a new profile (blank, or copied from another)").option("--from <existing>","Copy gateway URLs + config from an existing profile").option("--use","After creating, set this profile as active",!1).option("--json","Emit JSON result").action(($,Z)=>{try{let X={...Y.opts(),...Z},H=y$($);if(i$(H)){L(`Profile '${H}' already exists.`);return}let Q;if(Z.from){let z=y$(Z.from);if(!i$(z)){L(`--from: profile '${z}' does not exist.`);return}let V=V0(z);delete V["static-api-key"],delete V.agentRecordId,delete V.apiKeys,Q=V}else if(H in G2)Q=E2(H);else if(H in f0){let z=f0[H];Q={schemaVersion:void 0,globalGatewayUrl:z.globalGatewayUrl,workspaceGatewayUrl:z.workspaceGatewayUrl}}else Q={};if(R2(H,Q),Z.use)P0(H);if(B(X,{ok:!0,action:"create",profile:H,from:Z.from??null,globalGatewayUrl:Q.globalGatewayUrl??null,workspaceGatewayUrl:Q.workspaceGatewayUrl??null,active:Z.use===!0}))return;if(U(`Profile '${H}' created.`),Q.globalGatewayUrl)I("Global gateway",Q.globalGatewayUrl);if(Q.workspaceGatewayUrl)I("Workspace gateway",Q.workspaceGatewayUrl);if(Z.use)W(`Active profile is now '${H}'.`);else J(),W(`Activate with: ${K.bold(`vibe profile use ${H}`)}`)}catch(X){L(X.message)}}),q.command("use <name>").description("Set the active profile pointer").option("--json","Emit JSON result").action(($,Z)=>{try{let X={...Y.opts(),...Z},H=y$($);if(!i$(H)){L(`No profile named '${H}'. Create it with 'vibe profile create ${H}' first.`);return}if(P0(H),B(X,{ok:!0,action:"use",profile:H}))return;U(`Active profile is now '${H}'.`)}catch(X){L(X.message)}}),q.command("delete <name>").description("Delete a profile (refuses if it is the active one)").option("--confirm","Required -- destructive",!1).option("--json","Emit JSON result").action(($,Z)=>{try{let X={...Y.opts(),...Z},H=y$($);if(!Z.confirm){L(`Pass --confirm to delete profile '${H}' (this removes its config + secrets).`);return}if(!i$(H)){L(`No profile named '${H}'.`);return}if(H===f$()){L(`Cannot delete the active profile '${H}'. Switch first: 'vibe profile use <other>'.`);return}let Q=j2(H);if(B(X,{ok:Q,action:"delete",profile:H}))return;if(Q)U(`Deleted profile '${H}'.`);else L(`Profile '${H}' could not be removed.`)}catch(X){L(X.message)}}),q.command("seed").description("Idempotently create local/alpha/prod profiles").option("--json","Emit JSON result").action(($)=>{try{let Z={...Y.opts(),...$},X=N2();if(B(Z,{ok:!0,action:"seed",created:X.created,activeWritten:X.activeWritten??null}))return;if(X.created.length>0)U(`Created profile(s): ${X.created.join(", ")}`);if(X.activeWritten)W(`Active profile set to '${X.activeWritten}'.`);if(X.created.length===0&&!X.activeWritten)W("Nothing to do -- profiles already initialized.")}catch(Z){L(Z.message)}})}function x2(Y){let q=Y.command("daemon-profile").description("Manage the running daemon's in-process ProfileRegistry (distinct from `vibe profile`, which manages gateway-environment profiles on disk).");q.command("list").description("List profiles known to the running daemon").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){let Z={...Y.opts(),...$};try{await P({mode:f(Z),fetchData:()=>y(w(Z),"/api/profiles"),plain:(X)=>{if(T("Daemon Profiles"),J(),!X||X.length===0){W("No profiles attached.");return}let H=X.map((Q)=>({Name:Q.name,Default:Q.isDefault?"yes":"",Attached:Q.attached?"yes":"",BootState:Q.bootState??"-",Running:Q.isRunning?"yes":"",Port:Q.port??"-",PID:Q.pid??"-"}));n(H)}})}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(`Failed to list daemon profiles: ${C(X)}`)}}),q.command("create <name>").description("Create a new profile and attach it to the running daemon").option("--copy-from <source>","Copy config from an existing profile").option("--start","Spawn an out-of-process daemon for the new profile").option("--port <port>","Port for the spawned daemon (with --start)").option("--json","Emit JSON").action(async function($,Z){let X={...Y.opts(),...Z};try{let H={name:$};if(Z.copyFrom)H.copyFrom=Z.copyFrom;if(Z.start)H.start=!0;if(Z.port)H.port=parseInt(Z.port,10);let Q=await m(w(X),"/api/profiles",H);if(B(X,Q))return;if(U(`Profile '${$}' created.`),I("Default",Q.isDefault?"yes":"no"),I("Attached",Q.attached?"yes":"no"),Q.bootState)I("BootState",Q.bootState)}catch(H){if(X.json){B(X,{ok:!1,error:C(H)});return}L(`Failed to create profile: ${C(H)}`)}}),q.command("delete <name>").alias("rm").description("Delete a profile from the running daemon").option("--purge","Also remove the on-disk dataDir (destructive)").option("--json","Emit JSON").action(async function($,Z){let X={...Y.opts(),...Z};try{let H=Z.purge?`/api/profiles/${encodeURIComponent($)}?purge=true`:`/api/profiles/${encodeURIComponent($)}`,Q=await P$(w(X),H);if(B(X,Q))return;U(`Profile '${$}' deleted.`)}catch(H){if(X.json){B(X,{ok:!1,error:C(H)});return}L(`Failed to delete profile: ${C(H)}`)}}),q.command("start <name>").description("Ensure the profile is attached + running (idempotent)").option("--port <port>","Port for the spawned daemon").option("--json","Emit JSON").action(async function($,Z){let X={...Y.opts(),...Z};try{let H={};if(Z.port)H.port=parseInt(Z.port,10);let Q=await m(w(X),`/api/profiles/${encodeURIComponent($)}/start`,H);if(B(X,Q))return;if(U(`Profile '${$}' started.`),Q.bootState)I("BootState",Q.bootState);if(Q.port)I("Port",String(Q.port))}catch(H){if(X.json){B(X,{ok:!1,error:C(H)});return}L(`Failed to start profile: ${C(H)}`)}}),q.command("stop <name>").description("Stop the profile (detach from registry, preserve dataDir)").option("--json","Emit JSON").action(async function($,Z){let X={...Y.opts(),...Z};try{let H=await m(w(X),`/api/profiles/${encodeURIComponent($)}/stop`);if(B(X,H))return;U(`Profile '${$}' stopped.`)}catch(H){if(X.json){B(X,{ok:!1,error:C(H)});return}L(`Failed to stop profile: ${C(H)}`)}}),q.command("restart <name>").description("Stop then start the profile").option("--port <port>","Port for the spawned daemon").option("--json","Emit JSON").action(async function($,Z){let X={...Y.opts(),...Z};try{await m(w(X),`/api/profiles/${encodeURIComponent($)}/stop`);let H={};if(Z.port)H.port=parseInt(Z.port,10);let Q=await m(w(X),`/api/profiles/${encodeURIComponent($)}/start`,H);if(B(X,Q))return;if(U(`Profile '${$}' restarted.`),Q.bootState)I("BootState",Q.bootState)}catch(H){if(X.json){B(X,{ok:!1,error:C(H)});return}L(`Failed to restart profile: ${C(H)}`)}}),q.command("stats").description("Per-profile resource attribution (childPidCount, status, dataDir; CPU/heap reported at the process level)").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){let Z={...Y.opts(),...$};try{await P({mode:f(Z),fetchData:()=>y(w(Z),"/api/profile-stats"),plain:(X)=>{if(T("Profile Stats"),J(),I("PID",String(X.process.pid)),I("Uptime (s)",String(Math.round(X.process.uptimeSeconds))),I("CPU user (ms)",String(Math.round(X.process.cpuUserMs))),I("CPU system (ms)",String(Math.round(X.process.cpuSystemMs))),I("Heap used (MB)",String(Math.round(X.process.heapUsedBytes/1048576))),J(),!X.profiles||X.profiles.length===0){W("No profiles attached.");return}n(X.profiles.map((H)=>({Name:H.name,Status:H.status,ChildPids:String(H.childPidCount),DataDir:H.dataDir})))}})}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(`Failed to fetch profile stats: ${C(X)}`)}})}import b$ from"os";function R3(){return crypto.randomUUID()}function j3(){let Y=new Uint8Array(32);return crypto.getRandomValues(Y),`vcak_${Buffer.from(Y).toString("base64url")}`}function E3(){let Y=new Bun.CryptoHasher("sha256");return Y.update(`${b$.hostname()}-${b$.platform()}-${b$.arch()}`),Y.digest("hex").substring(0,16)}function N3(Y){if(!Y)return;let q=/^(\d+)([smhdw]?)$/.exec(Y.trim());if(!q)throw Error(`Invalid --expires-in: ${Y}`);let $=Number(q[1]),Z=q[2]||"d",X=Z==="s"?$*1000:Z==="m"?$*60000:Z==="h"?$*3600000:Z==="w"?$*7*86400000:$*86400000;return new Date(Date.now()+X).toISOString()}function A2(Y){Y.command("peer-bootstrap").description("Mint a peer credential bundle (used by `vibe deploy` post-install handshake)").option("--label <label>","Friendly name for the caller (logged on this host)","peer").option("--scope <list>",`Comma-separated permissions for the minted key (default: tunnel:read). Allowed: ${E$.join(",")}`,"tunnel:read").option("--expires-in <duration>","TTL for the minted key (e.g. 7d, 12h). Omit for no expiry.").option("--emit-default-key","Include this agent's FULL default API key in the bundle. Only used by `vibe deploy` over the trusted SSH channel to onboard the new agent to the backend (fresh OAuth app). Never expose this output otherwise.",!1).option("--no-output","Don't print the JSON bundle (for testing)").option("--json","Emit JSON bundle (default behaviour, kept for parity)").action(async function(q){try{let $=q.scope.split(",").map((G)=>G.trim()).filter(Boolean),Z=K0($);if(Z.length===0)throw Error(`No valid permissions in --scope. Allowed: ${E$.join(",")}`);let X=N3(q.expiresIn),H=R3(),Q=j3(),z=Z.includes("mesh:forward")?["read","mesh:forward"]:["read"],_=[...Y$().apiKeys??[],{id:H,name:`peer:${q.label}`,key:Q,scopes:z,expiresAt:X,createdAt:new Date().toISOString()}];U$({apiKeys:_});let O=Y$(),F=await M2(),D={id:E3(),hostname:b$.hostname(),platform:b$.platform(),arch:b$.arch(),tunnelUrl:w2()||J$()?.url||null,apiKey:Q,keyId:H,permissions:Z,expiresAt:X??null,defaultApiKey:F.substring(0,8)+"****",...q.emitDefaultKey?{fullDefaultApiKey:F}:{},agentRecordId:O.agentRecordId??null,workspaceId:O.workspaceId??null};if(q.output===!1)return;console.log(`VIBE_BOOTSTRAP_JSON=${JSON.stringify(D)}`);let R={...Y.opts(),...q};if(B(R,D))return;console.log(JSON.stringify(D,null,2))}catch($){console.error(JSON.stringify({error:$ instanceof Error?C($):String($)})),process.exit(1)}})}var D3=[{title:"Lifecycle",commands:["start","stop","restart","kill","list","status"]},{title:"Setup",commands:["setup","autostart","deploy","update","completion"]},{title:"Profile",commands:["profile"]},{title:"Plugins",commands:["plugin"]},{title:"Network",commands:["tunnel","network","peer-bootstrap","gateway-auth","url"]},{title:"Data",commands:["export","import","file","project","session","task","bookmark","state","git","key","config"]},{title:"Diagnostics",commands:["doctor","diagnostics","health","info","system","log","logs","log-level","notify"]},{title:"Maintenance",commands:["gc","nuke"]},{title:"Help",commands:["help"]}];function k0(Y){let q=new Map;for(let $ of Y.commands){if($._hidden)continue;let Z=$.name();q.set(Z,{name:Z,description:$.description()||"",cmd:$})}return q}function x3(Y,q){let $=Y;for(let Z of q){let X=$.commands.find((H)=>H.name()===Z||H.aliases().includes(Z));if(!X)return null;$=X}return $}function u0(Y){let q=new Set,$=[];for(let X of D3)for(let H of X.commands){let Q=Y.get(H);if(!Q)continue;q.add(H),$.push({group:X.title,entry:Q})}let Z=[...Y.values()].filter((X)=>!q.has(X.name));for(let X of Z.sort((H,Q)=>H.name.localeCompare(Q.name)))$.push({group:"Other",entry:X});return $}function M3(Y,q=!1){let $=k0(Y),Z=u0($),X=Z.length>0?Math.max(...Z.map((V)=>V.entry.name.length)):0,H=[];H.push(""),H.push(`${K.bold("vibe")} ${K.dim("\u2014 VibeControls Agent CLI")}`),H.push(""),H.push(`Usage: ${K.bold("vibe")} <command> [options]`),H.push(` ${K.bold("vibe help")} <command>`);let Q="";for(let{group:V,entry:_}of Z){if(V!==Q)H.push(""),H.push(K.cyan(V)),Q=V;let O=" ".repeat(X-_.name.length+2);H.push(` ${K.bold(_.name)}${O}${_.description}`)}H.push(""),H.push(K.dim("Tip: pipe to a TTY to launch the interactive browser, or run `vibe help <command>` for full options.")),H.push("");let z=H.join(`
217
+ `);return q?b0(z):z}function w3(Y){let q=k0(Y);return{commands:u0(q).map(({group:Z,entry:X})=>({name:X.name,description:X.description,group:Z}))}}function S2(Y,q=!1){process.stdout.write(M3(Y,q))}function h2(Y){process.stdout.write(Y.helpInformation())}async function A3(Y){let q;try{q=await import("./index-x649afed.js")}catch{return!1}let{createCliRenderer:$,BoxRenderable:Z,TextRenderable:X,SelectRenderable:H,SelectRenderableEvents:Q}=q,z=k0(Y),V=u0(z);if(V.length===0)return!1;let _=await $({exitOnCtrlC:!0,targetFps:30}),O=[],F="";for(let v of V){if(v.group!==F)O.push({kind:"header",title:v.group}),F=v.group;O.push({kind:"cmd",entry:v.entry})}let D=O.map((v,u)=>v.kind==="header"?{name:`\u2500\u2500 ${v.title} \u2500\u2500`,description:"",value:u}:{name:v.entry.name,description:v.entry.description,value:u}),R=_.root.ctx,G=new Z(R,{width:"100%",height:"100%",flexDirection:"column",backgroundColor:"#0b0d12"}),x=new X(R,{content:" vibe \u2014 command browser \u2191/\u2193 navigate \xB7 Enter view \xB7 q quit",fg:"#8be9fd",height:1}),M=new Z(R,{width:"100%",flexGrow:1,flexDirection:"row"}),N=new H(R,{width:28,height:"100%",options:D,selectedIndex:O.findIndex((v)=>v.kind==="cmd"),showDescription:!1,backgroundColor:"#0b0d12",textColor:"#cdd6f4",focusedBackgroundColor:"#0b0d12",focusedTextColor:"#cdd6f4",selectedBackgroundColor:"#1f2335",selectedTextColor:"#a6e3a1",showScrollIndicator:!0,wrapSelection:!1}),S=new Z(R,{flexGrow:1,height:"100%",flexDirection:"column",paddingLeft:2,paddingRight:2,backgroundColor:"#11141c"}),q$=new X(R,{content:"",fg:"#cdd6f4"});S.add(q$),M.add(N),M.add(S),G.add(x),G.add(M),_.root.add(G),N.focus();let o=(v)=>{let u=O[v];if(!u)return;if(u.kind==="header"){q$.content=`
218
+ ${u.title}
219
+ `;return}let c=u.entry.cmd.helpInformation();q$.content=`
220
220
  ${c}
221
221
  ${"\u2500".repeat(40)}
222
222
  Enter: print this help and exit
223
- `};return p(D.getSelectedIndex()),D.on(Q.SELECTION_CHANGED,(v)=>{p(v)}),await new Promise((v)=>{let P=(c)=>{try{I.destroy()}catch{}if(c)h2(c.cmd);v(!0)};D.on(Q.ITEM_SELECTED,()=>{let c=O[D.getSelectedIndex()];if(!c||c.kind!=="cmd")return;P(c.entry)}),I.keyInput.on("keypress",(c)=>{if(c.name==="escape"||c.name==="q")P(null)})})}function v2(Y){Y.command("help [command...]").description("Show categorised help \u2014 interactive in a TTY, plain otherwise").option("--plain","Force plain text output (no interactive UI)").option("--json","Emit machine-readable JSON instead of grouped text").action(async function(q,$){let Z={...Y.opts(),...$};{if(q&&q.length>0){let H=x3(Y,q);if(!H){let Q=`
223
+ `};return o(N.getSelectedIndex()),N.on(Q.SELECTION_CHANGED,(v)=>{o(v)}),await new Promise((v)=>{let u=(c)=>{try{_.destroy()}catch{}if(c)h2(c.cmd);v(!0)};N.on(Q.ITEM_SELECTED,()=>{let c=O[N.getSelectedIndex()];if(!c||c.kind!=="cmd")return;u(c.entry)}),_.keyInput.on("keypress",(c)=>{if(c.name==="escape"||c.name==="q")u(null)})})}function v2(Y){Y.command("help [command...]").description("Show categorised help \u2014 interactive in a TTY, plain otherwise").option("--plain","Force plain text output (no interactive UI)").option("--json","Emit machine-readable JSON instead of grouped text").action(async function(q,$){let Z={...Y.opts(),...$};{if(q&&q.length>0){let H=x3(Y,q);if(!H){let Q=`
224
224
  Unknown command: ${K.bold(q.join(" "))}
225
225
  `;console.error(Z.plain?b0(Q):Q),S2(Y,!!Z.plain),process.exitCode=1;return}if(Z.json){process.stdout.write(JSON.stringify({name:H.name(),description:H.description(),usage:H.helpInformation()})+`
226
226
  `);return}h2(H);return}if(Z.json){process.stdout.write(JSON.stringify(w3(Y))+`
227
- `);return}if(!Z.plain&&t$()){if(await A3(Y))return}S2(Y,!!Z.plain)}})}var S3="http://localhost:3005",h3=5000;function v3(Y,q,$){let Z=Number.parseInt(Y,10);if(!Number.isInteger(Z)||Z<1)return q;return Math.min(Z,$)}function y2(Y){Y.command("audit").description("View persistent audit log").command("list").description("List recent audit events").option("--since <iso>","Lower-bound ISO 8601 timestamp").option("--limit <n>","Maximum events to show","100").option("--event <pattern>","Filter by event name (supports * glob)").option("--agent-url <url>","Agent URL",S3).option("--json","Emit JSON (one object per line)").option("--plain","Force plain text output").action(async function($){try{let Z={...Y.opts(),...$},X=M(Z),H=encodeURIComponent(S(Z)),Q=new URLSearchParams;if(Q.set("limit",String(v3(String(Z.limit),100,h3))),Z.since)Q.set("since",String(Z.since));if(Z.event)Q.set("event",String(Z.event));let L=(await y(X,`/api/profiles/${H}/agent/audit?${Q.toString()}`)).events??[];if(Z.json){for(let I of L)process.stdout.write(`${JSON.stringify(I)}
228
- `);return}if(L.length===0){W("No audit events found.");return}T("Audit events"),J();for(let I of L){let O=I.timestamp?K.dim(G$(I.timestamp)):"",G=I.source?K.cyan(`[${I.source}]`):"",x=K.bold(I.event??"?"),F=I.payload?K.dim(JSON.stringify(I.payload)):"";console.log(` ${x} ${G} ${F} ${O}`)}}catch(Z){V(C(Z))}})}function f2(Y){let q=Y.command("alias").description("Manage per-profile aliases");q.command("list").description("List aliases for the current profile").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){try{let Z={...Y.opts(),...$},X=M(Z),H=encodeURIComponent(S(Z));await b({mode:f(Z),fetchData:async()=>{return(await y(X,`/api/profiles/${H}/agent/aliases`)).aliases??[]},plain:(Q)=>{if(T("Aliases"),J(),!Q.length){W("No aliases defined.");return}let z=Q.map((L)=>({Name:L.name,Command:L.command.length>60?`${L.command.slice(0,57)}\u2026`:L.command,Description:L.description??"-",Updated:G$(L.updatedAt)}));n(z),J()}})}catch(Z){V(C(Z))}}),q.command("get <name>").description("Show an alias by name").option("--json","Emit JSON").action(async function($,Z){try{let X={...Y.opts(),...Z},H=M(X),Q=encodeURIComponent(S(X)),z=await y(H,`/api/profiles/${Q}/agent/aliases/${encodeURIComponent($)}`);if(X.json){process.stdout.write(`${JSON.stringify(z,null,2)}
229
- `);return}T(`Alias: ${z.name}`),J(),console.log(` ${K.bold("Command: ")} ${z.command}`),console.log(` ${K.bold("Description:")} ${z.description??"-"}`),console.log(` ${K.bold("Cwd: ")} ${z.cwd??"$HOME (default)"}`),console.log(` ${K.bold("Profile: ")} ${z.profile}`),console.log(` ${K.bold("Created: ")} ${z.createdAt}`),console.log(` ${K.bold("Updated: ")} ${z.updatedAt}`),J()}catch(X){V(C(X))}}),q.command("create <name>").description("Create a new alias").requiredOption("--command <cmd>","The shell command to run").option("--description <text>","Optional description").option("--cwd <dir>","Working directory the command runs in (supports ~, absolute, or relative-to-$HOME). Defaults to $HOME.").action(async function($,Z){try{let X={...Y.opts(),...Z},H=M(X),Q=encodeURIComponent(S(X)),z=await m(H,`/api/profiles/${Q}/agent/aliases`,{name:$,command:Z.command,description:Z.description,cwd:Z.cwd});U(`Created alias '${z.name}'`)}catch(X){V(C(X))}}),q.command("update <name>").description("Update an existing alias").option("--command <cmd>","Replacement shell command").option("--description <text>","Replacement description").option("--cwd <dir>","Replacement working directory. Pass an empty string to reset to $HOME.").action(async function($,Z){try{if(Z.command===void 0&&Z.description===void 0&&Z.cwd===void 0){V("Provide --command, --description, or --cwd to update.");return}let X={...Y.opts(),...Z},H=M(X),Q=encodeURIComponent(S(X)),z=await L0(H,`/api/profiles/${Q}/agent/aliases/${encodeURIComponent($)}`,{command:Z.command,description:Z.description,cwd:Z.cwd});U(`Updated alias '${z.name}'`)}catch(X){V(C(X))}}),q.command("delete <name>").description("Delete an alias").action(async function($,Z){try{let X={...Y.opts(),...Z},H=M(X),Q=encodeURIComponent(S(X));await P$(H,`/api/profiles/${Q}/agent/aliases/${encodeURIComponent($)}`),U(`Deleted alias '${$}'`)}catch(X){V(C(X))}})}function k2(Y){Y.command("run <name> [args...]").description("Run a stored alias by name").allowUnknownOption(!0).action(async function(q,$=[],Z){try{let X={...Y.opts(),...Z},H=M(X),Q=encodeURIComponent(S(X)),z;try{z=await y(H,`/api/profiles/${Q}/agent/aliases/${encodeURIComponent(q)}`)}catch{console.error(`alias '${q}' not found`),c0().audit.emit("agent","alias.executed",{exit_code:1}),process.exit(1)}let{exitCode:L}=await b2(z,$);c0().audit.emit("agent","alias.executed",{exit_code:L}),P2("alias.executed",{exit_code:L}),process.exit(L)}catch(X){V(C(X))}})}function u2(Y){Y.command("retry-config").description("Force the background finalize-retry worker to attempt finalize immediately. Use when the gateway came back online and you don't want to wait the current backoff.").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=M($),X=await fetch(`${Z}/api/agent/retry-config`,{method:"POST"}),H;try{H=await X.json()}catch{if($.json)B($,{ok:!1,error:`agent returned non-JSON (HTTP ${X.status})`}),process.exit(1);V(`Agent returned non-JSON response (HTTP ${X.status}). The daemon may be on an older build without /api/agent/retry-config.`),process.exit(1);return}if($.json){if(B($,H),H.state!=="ready")process.exit(H.ok?0:3);return}if(X.status===409){T("Retry not available"),W(H.error??"No active finalize-retry worker."),process.exit(2);return}if(T("Force finalize retry"),_("Result",H.ok?K.green("ok"):K.red("failed")),H.state)_("Boot state",H.state);if(H.worker){if(_("Attempt",String(H.worker.attempt)),H.worker.nextAttemptAt)_("Next attempt",H.worker.nextAttemptAt)}if(J(),H.ok&&H.state==="ready")W(`${K.green("\u2713")} Agent finalized \u2014 state=ready.`),process.exit(0);else if(H.ok)W(`${K.yellow("\u26A0")} Attempt completed but agent is still in '${H.state}'. The worker will continue to retry in the background; check ${K.bold("vibe status")} for progress.`),process.exit(0);else j(`Retry failed: ${H.error??"unknown error"}. The worker will keep retrying on the configured backoff. View the full trace with ${K.bold("vibe logs --since 10m")}.`),process.exit(3)}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X}),process.exit(1);return}V(`Failed to reach agent: ${X}`),process.exit(1)}})}var t="http://localhost:3005";function y3(Y){return(Y||[]).map((q)=>({id:q.id??null,name:q.name??null,status:q.status??null,port:q.port??null,project:q.project??q.projectId??null}))}async function c2(Y,q,$,Z,X){await b({mode:f(X),fetchData:async()=>{return(await y(Y,q)).sessions||[]},plain:(H)=>{if(!H||H.length===0){W(Z);return}T($),n(H.map((Q)=>({ID:W$(Q.id||""),Name:Q.name||"-",Status:x$(Q.status||""),Port:Q.port??"-",Project:Q.project||Q.projectId||"-"})))},interactive:async(H)=>{if(!H||H.length===0){T($),W(Z);return}let Q=H.map((z)=>({id:String(z.id??""),label:z.name||W$(z.id||""),hint:z.status||"",detail:[`ID: ${z.id??"-"}`,`Name: ${z.name??"-"}`,`Status: ${x$(z.status||"")}`,`Port: ${z.port??"-"}`,`Project: ${z.project??z.projectId??"-"}`].join(`
230
- `)}));await e({title:`${$} \u2014 ${H.length} session(s)`,rows:Q})},json:(H)=>y3(H)})}function d2(Y){let q=Y.command("session").description("Manage terminal sessions");q.command("system").description("List system sessions (alias for `session list --system`)").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z));await c2(X,`/api/profiles/${H}/sessions/system`,"System Sessions","No system sessions found.",Z)}catch(X){V(C(X))}}),q.command("list").description("List all sessions").option("--system","Show system sessions instead of user sessions").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z)),Q=$.system?`/api/profiles/${H}/sessions/system`:`/api/profiles/${H}/sessions`;await c2(X,Q,"Sessions","No sessions found.",Z)}catch(X){V(C(X))}}),q.command("create").description("Create a new session").requiredOption("--name <name>","Session name").option("--project <id>","Project ID","default").option("--command <cmd>","Initial command to run").option("--cwd <dir>","Working directory").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z)),Q={sessionName:$.name,projectId:$.project};if($.command)Q.command=$.command;if($.cwd)Q.startDirectory=$.cwd;let z=await m(X,`/api/profiles/${H}/sessions/create`,Q),L=z?.session?.id||z?.id||z?.sessionId;if(B(Z,{ok:!0,id:L,name:$.name,project:$.project}))return;U(`Session created: ${W$(L)}`),_("Name",$.name),_("Project",$.project)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(C(X))}}),q.command("kill").description("Kill a session").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z));if(await P$(X,`/api/profiles/${H}/sessions/${$.id}`),B(Z,{ok:!0,id:$.id}))return;U(`Session ${W$($.id)} killed.`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(C(X))}}),q.command("exec").description("Execute a command in a session").requiredOption("-i, --id <id>","Session ID").requiredOption("-c, --command <cmd>","Command to execute").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z)),Q=await m(X,`/api/profiles/${H}/sessions/${$.id}/command`,{command:$.command});if(B(Z,{ok:!0,id:$.id,output:Q?.output??null}))return;if(U("Command executed."),Q?.output)J(),console.log(Q.output)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(C(X))}}),q.command("capture").description("Capture session terminal output").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z));await b({mode:f(Z),fetchData:()=>y(X,`/api/profiles/${H}/sessions/${$.id}/capture`),plain:(Q)=>{if(Q?.content||Q?.output)console.log(Q.content||Q.output);else W("No capture data available.")},json:(Q)=>({id:$.id,content:Q?.content??Q?.output??null})})}catch(X){V(C(X))}}),q.command("keys").description("Send keys to a session").requiredOption("-i, --id <id>","Session ID").requiredOption("-k, --keys <keys>","Keys to send").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z));if(await m(X,`/api/profiles/${H}/sessions/${$.id}/keys`,{keys:$.keys}),B(Z,{ok:!0,id:$.id}))return;U("Keys sent.")}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(C(X))}}),q.command("interrupt").description("Send interrupt signal to a session").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z));if(await m(X,`/api/profiles/${H}/sessions/${$.id}/interrupt`,{}),B(Z,{ok:!0,id:$.id}))return;U(`Session ${W$($.id)} interrupted.`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(C(X))}}),q.command("rename").description("Rename a session").requiredOption("-i, --id <id>","Session ID").requiredOption("--name <name>","New session name").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z));if(await L0(X,`/api/profiles/${H}/sessions/${$.id}/rename`,{newName:$.name}),B(Z,{ok:!0,id:$.id,name:$.name}))return;U(`Session ${W$($.id)} renamed to "${$.name}".`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(C(X))}}),q.command("toggle-mouse").description("Toggle mouse support in a session").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z)),Q=await m(X,`/api/profiles/${H}/sessions/${$.id}/toggle-mouse`,{});if(B(Z,{ok:!0,id:$.id,mouseEnabled:!!Q?.mouseEnabled}))return;U(`Mouse support ${Q?.mouseEnabled?"enabled":"toggled"} for session ${W$($.id)}.`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(C(X))}}),q.command("terminal-start").description("Start terminal for a session").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z)),Q=await m(X,`/api/profiles/${H}/sessions/${$.id}/terminal`,{});if(B(Z,{ok:!0,id:$.id,port:Q?.port??null}))return;if(U(`Terminal started for session ${W$($.id)}.`),Q?.port)_("Port",Q.port)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(C(X))}}),q.command("terminal-stop").description("Stop terminal for a session").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z));if(await m(X,`/api/profiles/${H}/sessions/${$.id}/terminal/stop`,{}),B(Z,{ok:!0,id:$.id}))return;U(`Terminal stopped for session ${W$($.id)}.`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(C(X))}}),q.command("health-check").description("Run health check on all sessions").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=M($),H=encodeURIComponent(S(Z)),Q=await y(X,`/api/profiles/${H}/sessions`),z=await m(X,`/api/profiles/${H}/sessions/health-check`,{sessionIds:(Q.sessions||[]).map((L)=>L.id)});if(B(Z,{ok:!0,healthy:z?.healthy??null,checked:z?.checked??null,fixed:z?.fixed??null}))return;if(U("Health check completed."),z?.healthy!==void 0)_("Healthy",z.healthy);if(z?.checked!==void 0)_("Checked",z.checked);if(z?.fixed!==void 0)_("Fixed",z.fixed)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}V(C(X))}})}function m2(Y){Y.command("reuse-db").description("Point this agent at an EXISTING database (reuse data from another same-workspace agent)").option("--adapter <name>","Storage adapter to use (e.g. postgres, skalex). Defaults to the configured/default adapter.").option("--connection-string <conn>","Connection string for the adapter (e.g. postgres://user:pass@host/db)").option("--storage-options <json>","Raw adapter options as a JSON object (alternative/in addition to --connection-string)").option("--db-path <path>","Data directory the adapter should use (e.g. an existing Skalex agent-db dir)").option("-y, --yes","Skip the confirmation prompt").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z={};if(q.storageOptions){let Q;try{Q=JSON.parse(q.storageOptions)}catch{V("--storage-options must be valid JSON.");return}if(!Q||typeof Q!=="object"||Array.isArray(Q)){V("--storage-options must be a JSON object.");return}for(let[z,L]of Object.entries(Q))Z[z]=typeof L==="string"?L:JSON.stringify(L)}if(q.connectionString)Z.connectionString=String(q.connectionString);if(!q.adapter&&!q.dbPath&&Object.keys(Z).length===0){V("Nothing to set. Provide --adapter with --connection-string (or --storage-options), and/or --db-path.");return}if(!$.json){if(T("Reuse an existing database"),q.adapter)_("Adapter",K.bold(q.adapter));if(q.dbPath)_("Data path",K.bold(q.dbPath));if(Object.keys(Z).length>0)_("Options",K.dim(Object.keys(Z).join(", ")));J(),j(`${N.warning} Reuse is safe ONLY for a database from the SAME workspace \u2014 the encryption key is per-workspace, so a foreign DB won't decrypt (the agent will go degraded).`),j(`${N.warning} Two agents writing the same database concurrently can corrupt it. Keep this a single-writer setup unless your adapter is explicitly configured for shared writes.`),J()}if(!q.yes&&!$.json){if(!await T$(K.bold("Write this storage configuration to the agent config?"))){W("Cancelled.");return}}let X={};if(q.adapter)X.storageAdapter=String(q.adapter);if(Object.keys(Z).length>0)X.storageOptions=Z;if(q.dbPath)X.dbPath=String(q.dbPath);U$(X);let H=q$();if(B($,{ok:!0,storageAdapter:H.storageAdapter??null,dbPath:H.dbPath??null,storageOptionKeys:Object.keys(H.storageOptions??{})}))return;U(`${N.success} Storage configuration written. Run ${K.bold("vibe restart")} so the agent connects to the existing database.`)}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}V(`reuse-db failed: ${X}`)}})}function d0(Y){return new Set([...r$(Y)??$0()])}function m0(Y){return o$(process.platform,new Set(Y)).map((q)=>q.packageName)}async function g0(){let{PluginManager:Y}=await import("./plugin-system-c916v9an.js"),q=new Y;return{install:($)=>q.install($),remove:($)=>q.remove($)}}function l2(Y){let q=Y.command("capability").alias("cap").description("Select agent capabilities (abilities) + providers");q.command("list",{isDefault:!0}).description("List capabilities and whether each is enabled").option("--json","Emit JSON").action(($)=>{let Z={...Y.opts(),...$},X=Z$(),H=d0(X),Q=c$(X);if(B(Z,{abilities:k$.map((z)=>({key:z.key,label:z.label,mandatory:z.mandatory,enabled:z.mandatory||H.has(z.key)})),providers:Q}))return;if(T("Capabilities"),n(k$.map((z)=>({Key:z.key,Capability:z.label,Status:z.mandatory?"required":H.has(z.key)?"enabled":"disabled",Description:z.description}))),Q.length>0){J(),T("Extra providers");for(let z of Q)_("\u2022",z)}J(),W("Enable: vibe capability enable <key...> [--provider <pkg...>]"),W("Disable: vibe capability disable <key...>"),W("Re-run the interactive selector: vibe capability select")}),q.command("enable").description("Enable capabilities (installs their meta plugin) and/or extra providers").argument("[keys...]","Ability keys (e.g. gitops security)").option("--provider <pkg...>","Extra provider plugin(s) to install (short name or @vibecontrols/...)").option("--json","Emit JSON").action(async($,Z)=>{try{let X={...Y.opts(),...Z},H=Z$(),Q=new Set(k$.map((E)=>E.key)),z=($??[]).map((E)=>E.trim().toLowerCase()).filter((E)=>Q.has(E));for(let E of($??[]).filter((w)=>!Q.has(w.trim().toLowerCase())))j(`Unknown capability "${E}" \u2014 see \`vibe capability list\`.`);let I=(Array.isArray(Z.provider)?Z.provider:Z.provider?[Z.provider]:[]).map((E)=>g2(E)).filter((E)=>Boolean(E));if(z.length===0&&I.length===0){V("Provide at least one capability key or --provider <pkg>.");return}let O=d0(H);for(let E of z)O.add(E);let G=[...new Set([...m0(z),...I])],x=await g0(),F=[];for(let E of G)try{await x.install(E),F.push({package:E,ok:!0})}catch(w){F.push({package:E,ok:!1,error:C(w)})}let R=[...new Set([...c$(H),...I])];if(D$(H,{abilities:O,providers:R}),B(X,{ok:!0,action:"enable",abilities:[...O],providers:R,installed:F}))return;for(let E of F)if(E.ok)U(`Installed ${E.package}`);else j(`Failed to install ${E.package}: ${E.error}`);U("Capabilities updated. Restart the agent to load: vibe restart")}catch(X){V(C(X))}}),q.command("disable").description("Disable capabilities (removes their meta plugin)").argument("<keys...>","Ability keys").option("--json","Emit JSON").action(async($,Z)=>{try{let X={...Y.opts(),...Z},H=Z$(),Q=new Set(k$.map((F)=>F.key)),z=new Set(k$.filter((F)=>F.mandatory).map((F)=>F.key)),L=($??[]).map((F)=>F.trim().toLowerCase()).filter((F)=>Q.has(F));for(let F of L.filter((R)=>z.has(R)))j(`"${F}" is required and cannot be disabled.`);let I=L.filter((F)=>!z.has(F));if(I.length===0){V("Nothing to disable.");return}let O=d0(H);for(let F of I)O.delete(F);let G=await g0(),x=[];for(let F of m0(I))try{await G.remove(F),x.push({package:F,ok:!0})}catch(R){x.push({package:F,ok:!1,error:C(R)})}if(D$(H,{abilities:O}),B(X,{ok:!0,action:"disable",abilities:[...O],removed:x}))return;for(let F of x)if(F.ok)U(`Removed ${F.package}`);else j(`Failed to remove ${F.package}: ${F.error}`);U("Capabilities updated. Restart the agent to apply: vibe restart")}catch(X){V(C(X))}}),q.command("select").description("Re-run the interactive capability selector and apply it").option("--json","Emit JSON").action(async($)=>{try{let Z={...Y.opts(),...$},X=Z$(),H=await e$(),Q=await g0();for(let z of m0(H))try{await Q.install(z)}catch{}if(D$(X,{abilities:H}),B(Z,{ok:!0,action:"select",abilities:[...H]}))return;U(`Selection saved (${[...H].join(", ")||"none"}). Restart to apply: vibe restart`)}catch(Z){V(C(Z))}})}function _q(Y){Y1(Y),q1(Y),Z1(Y),W1(Y),K1(Y),L1(Y),J1(Y),C1(Y),A1(Y),h1(Y),b1(Y),m1(Y),l1(Y),Y2(Y),H2(Y),Q2(Y),V2(Y),O2(Y),C2(Y),D2(Y),x2(Y),A2(Y),v2(Y),y2(Y),f2(Y),k2(Y),u2(Y),d2(Y),m2(Y),l2(Y)}
227
+ `);return}if(!Z.plain&&t$()){if(await A3(Y))return}S2(Y,!!Z.plain)}})}var S3="http://localhost:3005",h3=5000;function v3(Y,q,$){let Z=Number.parseInt(Y,10);if(!Number.isInteger(Z)||Z<1)return q;return Math.min(Z,$)}function y2(Y){Y.command("audit").description("View persistent audit log").command("list").description("List recent audit events").option("--since <iso>","Lower-bound ISO 8601 timestamp").option("--limit <n>","Maximum events to show","100").option("--event <pattern>","Filter by event name (supports * glob)").option("--agent-url <url>","Agent URL",S3).option("--json","Emit JSON (one object per line)").option("--plain","Force plain text output").action(async function($){try{let Z={...Y.opts(),...$},X=w(Z),H=encodeURIComponent(A(Z)),Q=new URLSearchParams;if(Q.set("limit",String(v3(String(Z.limit),100,h3))),Z.since)Q.set("since",String(Z.since));if(Z.event)Q.set("event",String(Z.event));let V=(await y(X,`/api/profiles/${H}/agent/audit?${Q.toString()}`)).events??[];if(Z.json){for(let _ of V)process.stdout.write(`${JSON.stringify(_)}
228
+ `);return}if(V.length===0){W("No audit events found.");return}T("Audit events"),J();for(let _ of V){let O=_.timestamp?K.dim(G$(_.timestamp)):"",F=_.source?K.cyan(`[${_.source}]`):"",D=K.bold(_.event??"?"),R=_.payload?K.dim(JSON.stringify(_.payload)):"";console.log(` ${D} ${F} ${R} ${O}`)}}catch(Z){L(C(Z))}})}function f2(Y){let q=Y.command("alias").description("Manage per-profile aliases");q.command("list").description("List aliases for the current profile").option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){try{let Z={...Y.opts(),...$},X=w(Z),H=encodeURIComponent(A(Z));await P({mode:f(Z),fetchData:async()=>{return(await y(X,`/api/profiles/${H}/agent/aliases`)).aliases??[]},plain:(Q)=>{if(T("Aliases"),J(),!Q.length){W("No aliases defined.");return}let z=Q.map((V)=>({Name:V.name,Command:V.command.length>60?`${V.command.slice(0,57)}\u2026`:V.command,Description:V.description??"-",Updated:G$(V.updatedAt)}));n(z),J()}})}catch(Z){L(C(Z))}}),q.command("get <name>").description("Show an alias by name").option("--json","Emit JSON").action(async function($,Z){try{let X={...Y.opts(),...Z},H=w(X),Q=encodeURIComponent(A(X)),z=await y(H,`/api/profiles/${Q}/agent/aliases/${encodeURIComponent($)}`);if(X.json){process.stdout.write(`${JSON.stringify(z,null,2)}
229
+ `);return}T(`Alias: ${z.name}`),J(),console.log(` ${K.bold("Command: ")} ${z.command}`),console.log(` ${K.bold("Description:")} ${z.description??"-"}`),console.log(` ${K.bold("Cwd: ")} ${z.cwd??"$HOME (default)"}`),console.log(` ${K.bold("Profile: ")} ${z.profile}`),console.log(` ${K.bold("Created: ")} ${z.createdAt}`),console.log(` ${K.bold("Updated: ")} ${z.updatedAt}`),J()}catch(X){L(C(X))}}),q.command("create <name>").description("Create a new alias").requiredOption("--command <cmd>","The shell command to run").option("--description <text>","Optional description").option("--cwd <dir>","Working directory the command runs in (supports ~, absolute, or relative-to-$HOME). Defaults to $HOME.").action(async function($,Z){try{let X={...Y.opts(),...Z},H=w(X),Q=encodeURIComponent(A(X)),z=await m(H,`/api/profiles/${Q}/agent/aliases`,{name:$,command:Z.command,description:Z.description,cwd:Z.cwd});U(`Created alias '${z.name}'`)}catch(X){L(C(X))}}),q.command("update <name>").description("Update an existing alias").option("--command <cmd>","Replacement shell command").option("--description <text>","Replacement description").option("--cwd <dir>","Replacement working directory. Pass an empty string to reset to $HOME.").action(async function($,Z){try{if(Z.command===void 0&&Z.description===void 0&&Z.cwd===void 0){L("Provide --command, --description, or --cwd to update.");return}let X={...Y.opts(),...Z},H=w(X),Q=encodeURIComponent(A(X)),z=await L0(H,`/api/profiles/${Q}/agent/aliases/${encodeURIComponent($)}`,{command:Z.command,description:Z.description,cwd:Z.cwd});U(`Updated alias '${z.name}'`)}catch(X){L(C(X))}}),q.command("delete <name>").description("Delete an alias").action(async function($,Z){try{let X={...Y.opts(),...Z},H=w(X),Q=encodeURIComponent(A(X));await P$(H,`/api/profiles/${Q}/agent/aliases/${encodeURIComponent($)}`),U(`Deleted alias '${$}'`)}catch(X){L(C(X))}})}function k2(Y){Y.command("run <name> [args...]").description("Run a stored alias by name").allowUnknownOption(!0).action(async function(q,$=[],Z){try{let X={...Y.opts(),...Z},H=w(X),Q=encodeURIComponent(A(X)),z;try{z=await y(H,`/api/profiles/${Q}/agent/aliases/${encodeURIComponent(q)}`)}catch{console.error(`alias '${q}' not found`),c0().audit.emit("agent","alias.executed",{exit_code:1}),process.exit(1)}let{exitCode:V}=await b2(z,$);c0().audit.emit("agent","alias.executed",{exit_code:V}),P2("alias.executed",{exit_code:V}),process.exit(V)}catch(X){L(C(X))}})}function u2(Y){Y.command("retry-config").description("Force the background finalize-retry worker to attempt finalize immediately. Use when the gateway came back online and you don't want to wait the current backoff.").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z=w($),X=await fetch(`${Z}/api/agent/retry-config`,{method:"POST"}),H;try{H=await X.json()}catch{if($.json)B($,{ok:!1,error:`agent returned non-JSON (HTTP ${X.status})`}),process.exit(1);L(`Agent returned non-JSON response (HTTP ${X.status}). The daemon may be on an older build without /api/agent/retry-config.`),process.exit(1);return}if($.json){if(B($,H),H.state!=="ready")process.exit(H.ok?0:3);return}if(X.status===409){T("Retry not available"),W(H.error??"No active finalize-retry worker."),process.exit(2);return}if(T("Force finalize retry"),I("Result",H.ok?K.green("ok"):K.red("failed")),H.state)I("Boot state",H.state);if(H.worker){if(I("Attempt",String(H.worker.attempt)),H.worker.nextAttemptAt)I("Next attempt",H.worker.nextAttemptAt)}if(J(),H.ok&&H.state==="ready")W(`${K.green("\u2713")} Agent finalized \u2014 state=ready.`),process.exit(0);else if(H.ok)W(`${K.yellow("\u26A0")} Attempt completed but agent is still in '${H.state}'. The worker will continue to retry in the background; check ${K.bold("vibe status")} for progress.`),process.exit(0);else j(`Retry failed: ${H.error??"unknown error"}. The worker will keep retrying on the configured backoff. View the full trace with ${K.bold("vibe logs --since 10m")}.`),process.exit(3)}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X}),process.exit(1);return}L(`Failed to reach agent: ${X}`),process.exit(1)}})}var t="http://localhost:3005";function y3(Y){return(Y||[]).map((q)=>({id:q.id??null,name:q.name??null,status:q.status??null,port:q.port??null,project:q.project??q.projectId??null}))}async function c2(Y,q,$,Z,X){await P({mode:f(X),fetchData:async()=>{return(await y(Y,q)).sessions||[]},plain:(H)=>{if(!H||H.length===0){W(Z);return}T($),n(H.map((Q)=>({ID:W$(Q.id||""),Name:Q.name||"-",Status:x$(Q.status||""),Port:Q.port??"-",Project:Q.project||Q.projectId||"-"})))},interactive:async(H)=>{if(!H||H.length===0){T($),W(Z);return}let Q=H.map((z)=>({id:String(z.id??""),label:z.name||W$(z.id||""),hint:z.status||"",detail:[`ID: ${z.id??"-"}`,`Name: ${z.name??"-"}`,`Status: ${x$(z.status||"")}`,`Port: ${z.port??"-"}`,`Project: ${z.project??z.projectId??"-"}`].join(`
230
+ `)}));await r({title:`${$} \u2014 ${H.length} session(s)`,rows:Q})},json:(H)=>y3(H)})}function d2(Y){let q=Y.command("session").description("Manage terminal sessions");q.command("system").description("List system sessions (alias for `session list --system`)").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z));await c2(X,`/api/profiles/${H}/sessions/system`,"System Sessions","No system sessions found.",Z)}catch(X){L(C(X))}}),q.command("list").description("List all sessions").option("--system","Show system sessions instead of user sessions").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z)),Q=$.system?`/api/profiles/${H}/sessions/system`:`/api/profiles/${H}/sessions`;await c2(X,Q,"Sessions","No sessions found.",Z)}catch(X){L(C(X))}}),q.command("create").description("Create a new session").requiredOption("--name <name>","Session name").option("--project <id>","Project ID","default").option("--command <cmd>","Initial command to run").option("--cwd <dir>","Working directory").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z)),Q={sessionName:$.name,projectId:$.project};if($.command)Q.command=$.command;if($.cwd)Q.startDirectory=$.cwd;let z=await m(X,`/api/profiles/${H}/sessions/create`,Q),V=z?.session?.id||z?.id||z?.sessionId;if(B(Z,{ok:!0,id:V,name:$.name,project:$.project}))return;U(`Session created: ${W$(V)}`),I("Name",$.name),I("Project",$.project)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(C(X))}}),q.command("kill").description("Kill a session").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z));if(await P$(X,`/api/profiles/${H}/sessions/${$.id}`),B(Z,{ok:!0,id:$.id}))return;U(`Session ${W$($.id)} killed.`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(C(X))}}),q.command("exec").description("Execute a command in a session").requiredOption("-i, --id <id>","Session ID").requiredOption("-c, --command <cmd>","Command to execute").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z)),Q=await m(X,`/api/profiles/${H}/sessions/${$.id}/command`,{command:$.command});if(B(Z,{ok:!0,id:$.id,output:Q?.output??null}))return;if(U("Command executed."),Q?.output)J(),console.log(Q.output)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(C(X))}}),q.command("capture").description("Capture session terminal output").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").option("--plain","Force plain text output").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z));await P({mode:f(Z),fetchData:()=>y(X,`/api/profiles/${H}/sessions/${$.id}/capture`),plain:(Q)=>{if(Q?.content||Q?.output)console.log(Q.content||Q.output);else W("No capture data available.")},json:(Q)=>({id:$.id,content:Q?.content??Q?.output??null})})}catch(X){L(C(X))}}),q.command("keys").description("Send keys to a session").requiredOption("-i, --id <id>","Session ID").requiredOption("-k, --keys <keys>","Keys to send").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z));if(await m(X,`/api/profiles/${H}/sessions/${$.id}/keys`,{keys:$.keys}),B(Z,{ok:!0,id:$.id}))return;U("Keys sent.")}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(C(X))}}),q.command("interrupt").description("Send interrupt signal to a session").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z));if(await m(X,`/api/profiles/${H}/sessions/${$.id}/interrupt`,{}),B(Z,{ok:!0,id:$.id}))return;U(`Session ${W$($.id)} interrupted.`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(C(X))}}),q.command("rename").description("Rename a session").requiredOption("-i, --id <id>","Session ID").requiredOption("--name <name>","New session name").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z));if(await L0(X,`/api/profiles/${H}/sessions/${$.id}/rename`,{newName:$.name}),B(Z,{ok:!0,id:$.id,name:$.name}))return;U(`Session ${W$($.id)} renamed to "${$.name}".`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(C(X))}}),q.command("toggle-mouse").description("Toggle mouse support in a session").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z)),Q=await m(X,`/api/profiles/${H}/sessions/${$.id}/toggle-mouse`,{});if(B(Z,{ok:!0,id:$.id,mouseEnabled:!!Q?.mouseEnabled}))return;U(`Mouse support ${Q?.mouseEnabled?"enabled":"toggled"} for session ${W$($.id)}.`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(C(X))}}),q.command("terminal-start").description("Start terminal for a session").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z)),Q=await m(X,`/api/profiles/${H}/sessions/${$.id}/terminal`,{});if(B(Z,{ok:!0,id:$.id,port:Q?.port??null}))return;if(U(`Terminal started for session ${W$($.id)}.`),Q?.port)I("Port",Q.port)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(C(X))}}),q.command("terminal-stop").description("Stop terminal for a session").requiredOption("-i, --id <id>","Session ID").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z));if(await m(X,`/api/profiles/${H}/sessions/${$.id}/terminal/stop`,{}),B(Z,{ok:!0,id:$.id}))return;U(`Terminal stopped for session ${W$($.id)}.`)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(C(X))}}),q.command("health-check").description("Run health check on all sessions").option("--agent-url <url>","Agent URL",t).option("--json","Emit JSON").action(async function($){let Z={...Y.opts(),...$};try{let X=w($),H=encodeURIComponent(A(Z)),Q=await y(X,`/api/profiles/${H}/sessions`),z=await m(X,`/api/profiles/${H}/sessions/health-check`,{sessionIds:(Q.sessions||[]).map((V)=>V.id)});if(B(Z,{ok:!0,healthy:z?.healthy??null,checked:z?.checked??null,fixed:z?.fixed??null}))return;if(U("Health check completed."),z?.healthy!==void 0)I("Healthy",z.healthy);if(z?.checked!==void 0)I("Checked",z.checked);if(z?.fixed!==void 0)I("Fixed",z.fixed)}catch(X){if(Z.json){B(Z,{ok:!1,error:C(X)});return}L(C(X))}})}function m2(Y){Y.command("reuse-db").description("Point this agent at an EXISTING database (reuse data from another same-workspace agent)").option("--adapter <name>","Storage adapter to use (e.g. postgres, skalex). Defaults to the configured/default adapter.").option("--connection-string <conn>","Connection string for the adapter (e.g. postgres://user:pass@host/db)").option("--storage-options <json>","Raw adapter options as a JSON object (alternative/in addition to --connection-string)").option("--db-path <path>","Data directory the adapter should use (e.g. an existing Skalex agent-db dir)").option("-y, --yes","Skip the confirmation prompt").option("--json","Emit JSON").action(async function(q){let $={...Y.opts(),...q};try{let Z={};if(q.storageOptions){let Q;try{Q=JSON.parse(q.storageOptions)}catch{L("--storage-options must be valid JSON.");return}if(!Q||typeof Q!=="object"||Array.isArray(Q)){L("--storage-options must be a JSON object.");return}for(let[z,V]of Object.entries(Q))Z[z]=typeof V==="string"?V:JSON.stringify(V)}if(q.connectionString)Z.connectionString=String(q.connectionString);if(!q.adapter&&!q.dbPath&&Object.keys(Z).length===0){L("Nothing to set. Provide --adapter with --connection-string (or --storage-options), and/or --db-path.");return}if(!$.json){if(T("Reuse an existing database"),q.adapter)I("Adapter",K.bold(q.adapter));if(q.dbPath)I("Data path",K.bold(q.dbPath));if(Object.keys(Z).length>0)I("Options",K.dim(Object.keys(Z).join(", ")));J(),j(`${E.warning} Reuse is safe ONLY for a database from the SAME workspace \u2014 the encryption key is per-workspace, so a foreign DB won't decrypt (the agent will go degraded).`),j(`${E.warning} Two agents writing the same database concurrently can corrupt it. Keep this a single-writer setup unless your adapter is explicitly configured for shared writes.`),J()}if(!q.yes&&!$.json){if(!await T$(K.bold("Write this storage configuration to the agent config?"))){W("Cancelled.");return}}let X={};if(q.adapter)X.storageAdapter=String(q.adapter);if(Object.keys(Z).length>0)X.storageOptions=Z;if(q.dbPath)X.dbPath=String(q.dbPath);U$(X);let H=Y$();if(B($,{ok:!0,storageAdapter:H.storageAdapter??null,dbPath:H.dbPath??null,storageOptionKeys:Object.keys(H.storageOptions??{})}))return;U(`${E.success} Storage configuration written. Run ${K.bold("vibe restart")} so the agent connects to the existing database.`)}catch(Z){let X=Z instanceof Error?C(Z):String(Z);if($.json){B($,{ok:!1,error:X});return}L(`reuse-db failed: ${X}`)}})}function d0(Y){return new Set([...r$(Y)??$0()])}function m0(Y){return o$(process.platform,new Set(Y)).map((q)=>q.packageName)}async function g0(){let{PluginManager:Y}=await import("./plugin-system-8hby8x1m.js"),q=new Y;return{install:($)=>q.install($),remove:($)=>q.remove($)}}function l2(Y){let q=Y.command("capability").alias("cap").description("Select agent capabilities (abilities) + providers");q.command("list",{isDefault:!0}).description("List capabilities and whether each is enabled").option("--json","Emit JSON").action(($)=>{let Z={...Y.opts(),...$},X=Z$(),H=d0(X),Q=c$(X);if(B(Z,{abilities:k$.map((z)=>({key:z.key,label:z.label,mandatory:z.mandatory,enabled:z.mandatory||H.has(z.key)})),providers:Q}))return;if(T("Capabilities"),n(k$.map((z)=>({Key:z.key,Capability:z.label,Status:z.mandatory?"required":H.has(z.key)?"enabled":"disabled",Description:z.description}))),Q.length>0){J(),T("Extra providers");for(let z of Q)I("\u2022",z)}J(),W("Enable: vibe capability enable <key...> [--provider <pkg...>]"),W("Disable: vibe capability disable <key...>"),W("Re-run the interactive selector: vibe capability select")}),q.command("enable").description("Enable capabilities (installs their meta plugin) and/or extra providers").argument("[keys...]","Ability keys (e.g. gitops security)").option("--provider <pkg...>","Extra provider plugin(s) to install (short name or @vibecontrols/...)").option("--json","Emit JSON").action(async($,Z)=>{try{let X={...Y.opts(),...Z},H=Z$(),Q=new Set(k$.map((x)=>x.key)),z=($??[]).map((x)=>x.trim().toLowerCase()).filter((x)=>Q.has(x));for(let x of($??[]).filter((M)=>!Q.has(M.trim().toLowerCase())))j(`Unknown capability "${x}" \u2014 see \`vibe capability list\`.`);let _=(Array.isArray(Z.provider)?Z.provider:Z.provider?[Z.provider]:[]).map((x)=>g2(x)).filter((x)=>Boolean(x));if(z.length===0&&_.length===0){L("Provide at least one capability key or --provider <pkg>.");return}let O=d0(H);for(let x of z)O.add(x);let F=[...new Set([...m0(z),..._])],D=await g0(),R=[];for(let x of F)try{await D.install(x),R.push({package:x,ok:!0})}catch(M){R.push({package:x,ok:!1,error:C(M)})}let G=[...new Set([...c$(H),..._])];if(D$(H,{abilities:O,providers:G}),B(X,{ok:!0,action:"enable",abilities:[...O],providers:G,installed:R}))return;for(let x of R)if(x.ok)U(`Installed ${x.package}`);else j(`Failed to install ${x.package}: ${x.error}`);U("Capabilities updated. Restart the agent to load: vibe restart")}catch(X){L(C(X))}}),q.command("disable").description("Disable capabilities (removes their meta plugin)").argument("<keys...>","Ability keys").option("--json","Emit JSON").action(async($,Z)=>{try{let X={...Y.opts(),...Z},H=Z$(),Q=new Set(k$.map((R)=>R.key)),z=new Set(k$.filter((R)=>R.mandatory).map((R)=>R.key)),V=($??[]).map((R)=>R.trim().toLowerCase()).filter((R)=>Q.has(R));for(let R of V.filter((G)=>z.has(G)))j(`"${R}" is required and cannot be disabled.`);let _=V.filter((R)=>!z.has(R));if(_.length===0){L("Nothing to disable.");return}let O=d0(H);for(let R of _)O.delete(R);let F=await g0(),D=[];for(let R of m0(_))try{await F.remove(R),D.push({package:R,ok:!0})}catch(G){D.push({package:R,ok:!1,error:C(G)})}if(D$(H,{abilities:O}),B(X,{ok:!0,action:"disable",abilities:[...O],removed:D}))return;for(let R of D)if(R.ok)U(`Removed ${R.package}`);else j(`Failed to remove ${R.package}: ${R.error}`);U("Capabilities updated. Restart the agent to apply: vibe restart")}catch(X){L(C(X))}}),q.command("select").description("Re-run the interactive capability selector and apply it").option("--json","Emit JSON").action(async($)=>{try{let Z={...Y.opts(),...$},X=Z$(),H=await e$(),Q=await g0();for(let z of m0(H))try{await Q.install(z)}catch{}if(D$(X,{abilities:H}),B(Z,{ok:!0,action:"select",abilities:[...H]}))return;U(`Selection saved (${[...H].join(", ")||"none"}). Restart to apply: vibe restart`)}catch(Z){L(C(Z))}})}function _q(Y){Y1(Y),q1(Y),Z1(Y),W1(Y),K1(Y),L1(Y),J1(Y),C1(Y),A1(Y),h1(Y),b1(Y),m1(Y),l1(Y),Y2(Y),H2(Y),Q2(Y),V2(Y),O2(Y),C2(Y),D2(Y),x2(Y),A2(Y),v2(Y),y2(Y),f2(Y),k2(Y),u2(Y),d2(Y),m2(Y),l2(Y)}
231
231
  export{M3 as I,_q as J};