badgerclaw 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +64 -57
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,20 +1,21 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var as=Object.create;var ft=Object.defineProperty;var is=Object.getOwnPropertyDescriptor;var cs=Object.getOwnPropertyNames;var ls=Object.getPrototypeOf,ds=Object.prototype.hasOwnProperty;var M=(e,t)=>()=>(e&&(t=e(e=0)),t);var us=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),eo=(e,t)=>{for(var o in t)ft(e,o,{get:t[o],enumerable:!0})},on=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of cs(t))!ds.call(e,r)&&r!==o&&ft(e,r,{get:()=>t[r],enumerable:!(n=is(t,r))||n.enumerable});return e};var d=(e,t,o)=>(o=e!=null?as(ls(e)):{},on(t||!e||!e.__esModule?ft(o,"default",{value:e,enumerable:!0}):o,e)),nn=e=>on(ft({},"__esModule",{value:!0}),e);function _(){try{let e=Ve.default.readFileSync(no,"utf-8");return JSON.parse(e)}catch{return null}}function ht(e){Ve.default.mkdirSync(cn,{recursive:!0}),Ve.default.writeFileSync(no,JSON.stringify(e,null,2),{mode:384})}function Ke(){try{Ve.default.unlinkSync(no)}catch{}}function yt(){let e=_();return e?new Date(e.expires_at)>new Date:!1}function wt(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var Ve,oo,an,cn,no,L=M(()=>{"use strict";Ve=d(require("fs")),oo=d(require("path")),an=d(require("os")),cn=oo.default.join(an.default.homedir(),".badgerclaw"),no=oo.default.join(cn,"auth.json")});function ro(){return ln.default.createHash("sha256").update(`${X.default.hostname()}-${X.default.platform()}-${X.default.arch()}`).digest("hex").slice(0,16)}function Q(){let e=_();if(e?.instance_id)return e.instance_id;let t=ro();return`openclaw-${X.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function bt(){return{hostname:X.default.hostname(),os:X.default.platform(),arch:X.default.arch(),uptimeSeconds:Math.floor(X.default.uptime()),memFreeMb:Math.floor(X.default.freemem()/1024/1024)}}var X,ln,xe=M(()=>{"use strict";X=d(require("os")),ln=d(require("crypto"));L()});var dn,H,un,ae=M(()=>{"use strict";dn=process.env.BADGERCLAW_ENV==="local",H=process.env.BADGERCLAW_API_URL??(dn?"http://localhost:8000":"https://api.badger.signout.io"),un=process.env.BADGERCLAW_AUTH_URL??(dn?"http://localhost:5500":"https://badgerclaw.ai")});function pn(){return Je}function ms(e){if(!e)return null;let t=e.split(".");if(t.length!==3)return null;try{let o=t[1].replace(/-/g,"+").replace(/_/g,"/"),n=o.length%4===0?o:o+"=".repeat(4-o.length%4),r=JSON.parse(Buffer.from(n,"base64").toString("utf8"));return(typeof r?.sub=="string"?r.sub:null)||null}catch{return null}}async function so(){let e=_();if(!e?.refresh_token||!e?.email)return Je=e?e.refresh_token?"no email in auth.json \u2014 re-run `badgerclaw login`":"no refresh_token in auth.json \u2014 re-run `badgerclaw login`":"not logged in (auth.json missing)",null;let t=ms(e.access_token);try{let o=await Ye.default.post(`${St}/api/v1/user/token/refresh`,{refresh_token:e.refresh_token,email:e.email,...t?{cognito_username:t}:{}}),n=o.data?.result??o.data,r=n?.access_token;if(!r)return Je="server returned no access_token",null;let s=n.expires_in||3600,a=new Date(Date.now()+s*1e3).toISOString();return ht({...e,access_token:r,expires_at:a}),Je=null,r}catch(o){let n=o?.response?.status,r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";Je=n?`HTTP ${n}: ${r}`:`network error: ${r}`;let s=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(n===403&&mn.test(s))throw Ke(),new Re(s);return null}}function ao(e){return e.interceptors.response.use(t=>(t.data&&typeof t.data=="object"&&"result"in t.data&&"errors"in t.data&&(t.data=t.data.result),t),t=>{let o=t.response?.data?.errors;return o?.length&&(t.message=o[0]),Promise.reject(t)}),e}function gn(e){return e.interceptors.response.use(void 0,t=>{if(t.response?.status===403){let n=t.message||t.response?.data?.errors?.[0]||t.response?.data?.detail||"";if(mn.test(n))return Ke(),Promise.reject(new Re(n))}return Promise.reject(t)}),e}function fn(e){return e.interceptors.response.use(void 0,async t=>{let o=t.config;if(t.response?.status!==401||o._retried)return Promise.reject(t);o._retried=!0,_t||(_t=so().finally(()=>{_t=null}));let n=await _t;return n?(o.headers.Authorization=`Bearer ${n}`,e.request(o)):Promise.reject(t)}),e}function O(){let e=_(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=Ye.default.create({baseURL:St,headers:t});return ao(o),fn(o),gn(o),o}function hn(){return ao(Ye.default.create({baseURL:St,headers:{"Content-Type":"application/json"}}))}function ze(e){let t=Ye.default.create({baseURL:St,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return ao(t),fn(t),gn(t),t}var Ye,St,Re,mn,_t,Je,he=M(()=>{"use strict";Ye=d(require("axios"));L();ae();St=H,Re=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},mn=/account\s+has\s+been\s+(deleted|deactivated)/i,_t=null,Je=null});function _n(){try{let e=ie.default.statSync(ye);return Date.now()-e.mtimeMs>wn}catch{return!0}}function io(){try{return ie.default.mkdirSync(co.default.dirname(ye),{recursive:!0}),ie.default.writeFileSync(ye,String(process.pid),{flag:"wx"}),!0}catch{if(_n())try{return ie.default.unlinkSync(ye),ie.default.writeFileSync(ye,String(process.pid),{flag:"wx"}),!0}catch{return!1}return!1}}function Sn(){try{ie.default.unlinkSync(ye)}catch{}}async function kn(e){let t=!1;for(let o=0;o<ps;o++){if(io()){t=!0;break}await new Promise(n=>setTimeout(n,bn))}t||console.warn("[config-lock] Could not acquire lock after timeout \u2014 proceeding without lock");try{return await e()}finally{t&&Sn()}}function we(e){let t=io();if(!t&&_n()){try{ie.default.unlinkSync(ye)}catch{}t=io()}try{return e()}finally{t&&Sn()}}var ie,yn,co,ye,wn,bn,ps,Xe=M(()=>{"use strict";ie=d(require("fs")),yn=d(require("os")),co=d(require("path")),ye=co.default.join(yn.default.homedir(),".openclaw","openclaw.json.lock"),wn=1e4,bn=50,ps=Math.ceil(wn/bn)});var be=us((Vi,gs)=>{gs.exports={name:"badgerclaw",version:"0.3.1",engines:{node:">=18"},description:"BadgerClaw CLI \u2014 one-click bot provisioning",main:"dist/index.js",bin:{badgerclaw:"./dist/index.js"},files:["dist/","scripts/","assets/","README.md"],scripts:{build:"node build.mjs","verify-dist-version":`node -e "const v=require('./package.json').version; const d=require('fs').readFileSync('./dist/index.js','utf8'); if(!d.includes('version:\\"'+v+'\\"')){console.error('dist/index.js is stale \u2014 rebuild before publish (package.json='+v+')'); process.exit(1);} console.log('dist/index.js OK \u2014 version '+v);"`,prepublishOnly:"rm -rf dist && npm run build && npm run verify-dist-version",preuninstall:"node scripts/preuninstall.cjs",test:"tsx --test 'tests/**/*.test.ts'"},keywords:[],author:"",license:"ISC",dependencies:{"@modelcontextprotocol/sdk":"^1.29.0",axios:"^1.6.0",chalk:"^4.1.2",commander:"^12.0.0",eventsource:"^1.1.2",open:"^8.4.2",ora:"^5.4.1"},devDependencies:{"@types/eventsource":"^1.1.15","@types/node":"^20.0.0",esbuild:"^0.28.0",tsx:"^4.22.0",typescript:"^5.3.0"}}});function vt(e=bs){try{return mo.default.readdirSync(e,{withFileTypes:!0}).filter(t=>t.isDirectory()&&t.name.startsWith("badgerclaw-connect-")).map(t=>oe.default.join(e,t.name))}catch{return[]}}function _s(){return[...vt().map(t=>oe.default.join(t,"node_modules/@badgerclaw/connect/package.json")),oe.default.join(ws,"package.json"),oe.default.join(vn,"node_modules/@badgerclaw/connect/package.json"),oe.default.join(vn,"package.json")]}function po(){return"0.3.1"}function $t(){for(let e of _s())try{let t=mo.default.readFileSync(e,"utf-8"),o=JSON.parse(t);if(o.version&&(!o.name||o.name==="@badgerclaw/connect"||o.name==="badgerclaw")||o.version)return o.version}catch{}return null}function uo(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function G(){if((0,lo.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,lo.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:uo(t.stdout)||null}function Ss(e,t){let o=e.split(".").map(s=>parseInt(s,10)||0),n=t.split(".").map(s=>parseInt(s,10)||0),r=Math.max(o.length,n.length);for(let s=0;s<r;s++){let a=(o[s]??0)-(n[s]??0);if(a!==0)return a<0?-1:1}return 0}function $n(e,t=G()){return t?Ss(uo(t),uo(e))>=0:!1}async function ks(){let e=new AbortController,t=setTimeout(()=>e.abort(),hs);try{let o=await fetch(fs,{signal:e.signal});if(!o.ok)return null;let n=await o.json(),r=n.result&&typeof n.result=="object"?n.result:n;return{cli:r.cli??"unknown",plugin:r.plugin??"unknown",supported_openclaw:r.supported_openclaw??"unknown"}}catch{return null}finally{clearTimeout(t)}}function vs(e){let t=[];if(e.cli&&e.cli!=="unknown"){let n=po();n!==e.cli&&t.push({component:"cli",current:n,approved:e.cli})}if(!(G()!==null))return t;if(e.plugin&&e.plugin!=="unknown"){let n=$t();(n===null||n!==e.plugin)&&t.push({component:"plugin",current:n??"not installed",approved:e.plugin})}if(e.supported_openclaw&&e.supported_openclaw!=="unknown"){let n=G();(n===null||n!==e.supported_openclaw)&&t.push({component:"openclaw",current:n??"not installed",approved:e.supported_openclaw})}return t}function $s(e){return e[2]}function Cs(e){return!e||e.startsWith("-")?!0:ys.has(e)}function Is(e){let t=[];t.push(""),t.push(ce.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let n=o.component.padEnd(8);t.push(` ${n} ${ce.default.yellow(o.current)} \u2192 ${ce.default.green(o.approved)} ${ce.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(ce.default.green(" To fix, run:")),t.push(ce.default.green.bold(" badgerclaw setup")),t.push(""),t.push(ce.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
3
- `)}async function Cn(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=$s(e);if(Cs(t))return;let o=await ks();if(!o)return;let n=vs(o);n.length!==0&&(process.stderr.write(Is(n)),process.exit(1))}var mo,kt,oe,lo,ce,fs,hs,ys,vn,ws,bs,Ae=M(()=>{"use strict";mo=d(require("fs")),kt=d(require("os")),oe=d(require("path")),lo=require("child_process"),ce=d(require("chalk"));ae();fs=`${H}/api/v1/dashboard/versions/latest`,hs=2500,ys=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),vn=oe.default.join(kt.default.homedir(),".openclaw/extensions/badgerclaw"),ws=oe.default.join(kt.default.homedir(),".openclaw/npm/node_modules/@badgerclaw/connect"),bs=oe.default.join(kt.default.homedir(),".openclaw/npm/projects")});var En={};eo(En,{HERMES_IMAGE_DEFAULT:()=>Ee,detectCapabilities:()=>le,detectDiskFreeGb:()=>An,detectDocker:()=>Ct,detectHermes:()=>It,detectOpenClaw:()=>Rn});function Ct(){if((0,Qe.spawnSync)("which",["docker"],{encoding:"utf-8"}).status!==0)return{installed:!1};let t=(0,Qe.spawnSync)("docker",["version","--format","{{.Server.Version}}"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout.trim()?{installed:!1}:{installed:!0,version:t.stdout.trim()}}function Rn(){let e=G();return e?{installed:!0,version:e}:{installed:!1}}function It(e){if(!e.installed)return{installed:!1};let t=process.env.HERMES_IMAGE||Ee;return(0,Qe.spawnSync)("docker",["image","inspect","--format","{{.RepoDigests}}",t],{encoding:"utf-8",timeout:3e3}).status!==0?{installed:!1}:{installed:!0,image:t}}function An(){let e=xn.default.join(go.default.homedir(),".badgerclaw"),t=In.default.existsSync(e)?e:go.default.homedir();if(process.platform==="win32")return null;let o=(0,Qe.spawnSync)("df",["-Pk",t],{encoding:"utf-8",timeout:3e3});if(o.status!==0||!o.stdout)return null;let n=o.stdout.trim().split(`
4
- `);if(n.length<2)return null;let r=n[1].split(/\s+/),s=parseInt(r[3]||"",10);return Number.isFinite(s)?Math.floor(s/1024/1024):null}function le(){let e=Ct();return{openclaw:Rn(),hermes:It(e),docker:e,disk_free_gb:An(),ports_in_use:[]}}var Qe,In,go,xn,Ee,_e=M(()=>{"use strict";Qe=require("child_process"),In=d(require("fs")),go=d(require("os")),xn=d(require("path"));Ae();Ee="hermes-agent-bc:bundled"});function Rt(e){return Z.default.join(xs,`bot-${e}`)}function ho(e){return`badgerclaw-hermes-bot-${e}`}function yo(){if(!N.default.existsSync(fo))return{hermes_bots:{}};try{let e=N.default.readFileSync(fo,"utf-8"),t=JSON.parse(e);return{hermes_bots:t.hermes_bots&&typeof t.hermes_bots=="object"?t.hermes_bots:{}}}catch{return{hermes_bots:{}}}}function As(e){N.default.existsSync(xt)||N.default.mkdirSync(xt,{recursive:!0,mode:448}),N.default.writeFileSync(fo,JSON.stringify(e,null,2)+`
5
- `,{mode:384})}function Es(e,t=Rs){let o=new Set(Object.values(e.hermes_bots).map(r=>r.port)),n=t;for(;o.has(n)||!Ps(n);)if(n+=1,n-t>1e3)throw new Error(`Could not find a free port near ${t} after 1000 tries \u2014 host is unusually busy`);return n}function Ps(e){let t=On.default.createServer(),o=!1;try{t.listen(e,"127.0.0.1"),o=!0}catch{o=!1}finally{try{t.close()}catch{}}return o}function Tn(e=process.env){let t=e.BADGERCLAW_LLM_PROVIDER?.toLowerCase(),o=e.BADGERCLAW_LLM_API_KEY;if(t&&o){if(t!=="gemini"&&t!=="anthropic"&&t!=="openrouter")throw new Error(`BADGERCLAW_LLM_PROVIDER must be one of: gemini, anthropic, openrouter. Got '${t}'.`);return{provider:t,apiKey:o}}let n=e.GOOGLE_API_KEY||e.GEMINI_API_KEY;if(n)return{provider:"gemini",apiKey:n};if(e.ANTHROPIC_API_KEY)return{provider:"anthropic",apiKey:e.ANTHROPIC_API_KEY};if(e.OPENROUTER_API_KEY)return{provider:"openrouter",apiKey:e.OPENROUTER_API_KEY}}function Ds(e){switch(e){case"gemini":return"gemini-2.5-flash";case"anthropic":return"claude-sonnet-4-6";case"openrouter":return"anthropic/claude-sonnet-4-6"}}function Os(e){switch(e){case"gemini":return"GOOGLE_API_KEY";case"anthropic":return"ANTHROPIC_API_KEY";case"openrouter":return"OPENROUTER_API_KEY"}}function Ns(e,t){let o=[`# Generated by badgerclaw CLI for bot ${e.botId}.`,"# Edit at your own risk; subsequent pair operations may overwrite.","",`MATRIX_HOMESERVER=${e.matrixHomeserver}`,`MATRIX_ACCESS_TOKEN=${e.matrixAccessToken}`,`MATRIX_USER_ID=${e.matrixUserId}`,`MATRIX_DEVICE_ID=${e.matrixDeviceId}`,"MATRIX_ENCRYPTION=true",`MATRIX_ALLOWED_USERS=${e.ownerMatrixUserId}`];return e.homeRoomId&&o.push(`MATRIX_HOME_ROOM=${e.homeRoomId}`),e.llm&&(o.push(""),o.push("# LLM provider \u2014 set by the operator's environment at pair time."),o.push("# Hermes reads this directly; model selection lives in config.yaml."),o.push(`${Os(e.llm.provider)}=${e.llm.apiKey}`)),o.push("","# OpenAI-compatible API surface \u2014 localhost only by default so the","# CLI's daemon can health-check the container without exposing it","# beyond the host loopback.","API_SERVER_ENABLED=true","API_SERVER_HOST=127.0.0.1",`API_SERVER_PORT=${t}`,`API_SERVER_KEY=${(0,Dn.randomBytes)(24).toString("hex")}`),o.join(`
2
+ "use strict";var ys=Object.create;var yt=Object.defineProperty;var ws=Object.getOwnPropertyDescriptor;var bs=Object.getOwnPropertyNames;var _s=Object.getPrototypeOf,Ss=Object.prototype.hasOwnProperty;var H=(e,t)=>()=>(e&&(t=e(e=0)),t);var ks=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),to=(e,t)=>{for(var o in t)yt(e,o,{get:t[o],enumerable:!0})},an=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of bs(t))!Ss.call(e,r)&&r!==o&&yt(e,r,{get:()=>t[r],enumerable:!(n=ws(t,r))||n.enumerable});return e};var u=(e,t,o)=>(o=e!=null?ys(_s(e)):{},an(t||!e||!e.__esModule?yt(o,"default",{value:e,enumerable:!0}):o,e)),ln=e=>an(yt({},"__esModule",{value:!0}),e);function b(){try{let e=Ye.default.readFileSync(ro,"utf-8");return JSON.parse(e)}catch{return null}}function wt(e){Ye.default.mkdirSync(mn,{recursive:!0}),Ye.default.writeFileSync(ro,JSON.stringify(e,null,2),{mode:384})}function Je(){try{Ye.default.unlinkSync(ro)}catch{}}function bt(){let e=b();return e?new Date(e.expires_at)>new Date:!1}function _t(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var Ye,no,un,mn,ro,M=H(()=>{"use strict";Ye=u(require("fs")),no=u(require("path")),un=u(require("os")),mn=no.default.join(un.default.homedir(),".badgerclaw"),ro=no.default.join(mn,"auth.json")});function so(){return pn.default.createHash("sha256").update(`${Q.default.hostname()}-${Q.default.platform()}-${Q.default.arch()}`).digest("hex").slice(0,16)}function Z(){let e=b();if(e?.instance_id)return e.instance_id;let t=so();return`openclaw-${Q.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function St(){return{hostname:Q.default.hostname(),os:Q.default.platform(),arch:Q.default.arch(),uptimeSeconds:Math.floor(Q.default.uptime()),memFreeMb:Math.floor(Q.default.freemem()/1024/1024)}}var Q,pn,xe=H(()=>{"use strict";Q=u(require("os")),pn=u(require("crypto"));M()});var gn,N,fn,oe=H(()=>{"use strict";gn=process.env.BADGERCLAW_ENV==="local",N=process.env.BADGERCLAW_API_URL??(gn?"http://localhost:8000":"https://api.badger.signout.io"),fn=process.env.BADGERCLAW_AUTH_URL??(gn?"http://localhost:5500":"https://badgerclaw.ai")});function yn(){return ze}function vs(e){if(!e)return null;let t=e.split(".");if(t.length!==3)return null;try{let o=t[1].replace(/-/g,"+").replace(/_/g,"/"),n=o.length%4===0?o:o+"=".repeat(4-o.length%4),r=JSON.parse(Buffer.from(n,"base64").toString("utf8"));return(typeof r?.sub=="string"?r.sub:null)||null}catch{return null}}async function ao(){let e=b();if(!e?.refresh_token||!e?.email)return ze=e?e.refresh_token?"no email in auth.json \u2014 re-run `badgerclaw login`":"no refresh_token in auth.json \u2014 re-run `badgerclaw login`":"not logged in (auth.json missing)",null;let t=vs(e.access_token);try{let o=await Xe.default.post(`${vt}/api/v1/user/token/refresh`,{refresh_token:e.refresh_token,email:e.email,...t?{cognito_username:t}:{}}),n=o.data?.result??o.data,r=n?.access_token;if(!r)return ze="server returned no access_token",null;let s=n.expires_in||3600,a=new Date(Date.now()+s*1e3).toISOString();return wt({...e,access_token:r,expires_at:a}),ze=null,r}catch(o){let n=o?.response?.status,r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";ze=n?`HTTP ${n}: ${r}`:`network error: ${r}`;let s=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(n===403&&hn.test(s))throw Je(),new Ae(s);return null}}function io(e){return e.interceptors.response.use(t=>(t.data&&typeof t.data=="object"&&"result"in t.data&&"errors"in t.data&&(t.data=t.data.result),t),t=>{let o=t.response?.data?.errors;return o?.length&&(t.message=o[0]),Promise.reject(t)}),e}function wn(e){return e.interceptors.response.use(void 0,t=>{if(t.response?.status===403){let n=t.message||t.response?.data?.errors?.[0]||t.response?.data?.detail||"";if(hn.test(n))return Je(),Promise.reject(new Ae(n))}return Promise.reject(t)}),e}function bn(e){return e.interceptors.response.use(void 0,async t=>{let o=t.config;if(t.response?.status!==401||o._retried)return Promise.reject(t);o._retried=!0,kt||(kt=ao().finally(()=>{kt=null}));let n=await kt;return n?(o.headers.Authorization=`Bearer ${n}`,e.request(o)):Promise.reject(t)}),e}function L(){let e=b(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=Xe.default.create({baseURL:vt,headers:t});return io(o),bn(o),wn(o),o}function _n(){return io(Xe.default.create({baseURL:vt,headers:{"Content-Type":"application/json"}}))}function Qe(e){let t=Xe.default.create({baseURL:vt,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return io(t),bn(t),wn(t),t}var Xe,vt,Ae,hn,kt,ze,he=H(()=>{"use strict";Xe=u(require("axios"));M();oe();vt=N,Ae=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},hn=/account\s+has\s+been\s+(deleted|deactivated)/i,kt=null,ze=null});function $n(){try{let e=ie.default.statSync(ye);return Date.now()-e.mtimeMs>kn}catch{return!0}}function lo(){try{return ie.default.mkdirSync(co.default.dirname(ye),{recursive:!0}),ie.default.writeFileSync(ye,String(process.pid),{flag:"wx"}),!0}catch{if($n())try{return ie.default.unlinkSync(ye),ie.default.writeFileSync(ye,String(process.pid),{flag:"wx"}),!0}catch{return!1}return!1}}function Cn(){try{ie.default.unlinkSync(ye)}catch{}}async function In(e){let t=!1;for(let o=0;o<$s;o++){if(lo()){t=!0;break}await new Promise(n=>setTimeout(n,vn))}t||console.warn("[config-lock] Could not acquire lock after timeout \u2014 proceeding without lock");try{return await e()}finally{t&&Cn()}}function we(e){let t=lo();if(!t&&$n()){try{ie.default.unlinkSync(ye)}catch{}t=lo()}try{return e()}finally{t&&Cn()}}var ie,Sn,co,ye,kn,vn,$s,Ze=H(()=>{"use strict";ie=u(require("fs")),Sn=u(require("os")),co=u(require("path")),ye=co.default.join(Sn.default.homedir(),".openclaw","openclaw.json.lock"),kn=1e4,vn=50,$s=Math.ceil(kn/vn)});var be=ks((ul,Cs)=>{Cs.exports={name:"badgerclaw",version:"0.3.2",engines:{node:">=18"},description:"BadgerClaw CLI \u2014 one-click bot provisioning",main:"dist/index.js",bin:{badgerclaw:"./dist/index.js"},files:["dist/","scripts/","assets/","README.md"],scripts:{build:"node build.mjs","verify-dist-version":`node -e "const v=require('./package.json').version; const d=require('fs').readFileSync('./dist/index.js','utf8'); if(!d.includes('version:\\"'+v+'\\"')){console.error('dist/index.js is stale \u2014 rebuild before publish (package.json='+v+')'); process.exit(1);} console.log('dist/index.js OK \u2014 version '+v);"`,prepublishOnly:"rm -rf dist && npm run build && npm run verify-dist-version",preuninstall:"node scripts/preuninstall.cjs",test:"tsx --test 'tests/**/*.test.ts'"},keywords:[],author:"",license:"ISC",dependencies:{"@modelcontextprotocol/sdk":"^1.29.0",axios:"^1.6.0",chalk:"^4.1.2",commander:"^12.0.0",eventsource:"^1.1.2",open:"^8.4.2",ora:"^5.4.1"},devDependencies:{"@types/eventsource":"^1.1.15","@types/node":"^20.0.0",esbuild:"^0.28.0",tsx:"^4.22.0",typescript:"^5.3.0"}}});function Ct(e=Es){try{return po.default.readdirSync(e,{withFileTypes:!0}).filter(t=>t.isDirectory()&&t.name.startsWith("badgerclaw-connect-")).map(t=>ne.default.join(e,t.name))}catch{return[]}}function Ps(){return[...Ct().map(t=>ne.default.join(t,"node_modules/@badgerclaw/connect/package.json")),ne.default.join(As,"package.json"),ne.default.join(Rn,"node_modules/@badgerclaw/connect/package.json"),ne.default.join(Rn,"package.json")]}function go(){return"0.3.2"}function It(){for(let e of Ps())try{let t=po.default.readFileSync(e,"utf-8"),o=JSON.parse(t);if(o.version&&(!o.name||o.name==="@badgerclaw/connect"||o.name==="badgerclaw")||o.version)return o.version}catch{}return null}function mo(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function G(){if((0,uo.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,uo.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:mo(t.stdout)||null}function Ds(e,t){let o=e.split(".").map(s=>parseInt(s,10)||0),n=t.split(".").map(s=>parseInt(s,10)||0),r=Math.max(o.length,n.length);for(let s=0;s<r;s++){let a=(o[s]??0)-(n[s]??0);if(a!==0)return a<0?-1:1}return 0}function xn(e,t=G()){return t?Ds(mo(t),mo(e))>=0:!1}async function Os(){let e=new AbortController,t=setTimeout(()=>e.abort(),Rs);try{let o=await fetch(Is,{signal:e.signal});if(!o.ok)return null;let n=await o.json(),r=n.result&&typeof n.result=="object"?n.result:n;return{cli:r.cli??"unknown",plugin:r.plugin??"unknown",supported_openclaw:r.supported_openclaw??"unknown"}}catch{return null}finally{clearTimeout(t)}}function Ls(e){let t=[];if(e.cli&&e.cli!=="unknown"){let n=go();n!==e.cli&&t.push({component:"cli",current:n,approved:e.cli})}if(!(G()!==null))return t;if(e.plugin&&e.plugin!=="unknown"){let n=It();(n===null||n!==e.plugin)&&t.push({component:"plugin",current:n??"not installed",approved:e.plugin})}if(e.supported_openclaw&&e.supported_openclaw!=="unknown"){let n=G();(n===null||n!==e.supported_openclaw)&&t.push({component:"openclaw",current:n??"not installed",approved:e.supported_openclaw})}return t}function Ns(e){return e[2]}function Ts(e){return!e||e.startsWith("-")?!0:xs.has(e)}function Ms(e){let t=[];t.push(""),t.push(le.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let n=o.component.padEnd(8);t.push(` ${n} ${le.default.yellow(o.current)} \u2192 ${le.default.green(o.approved)} ${le.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(le.default.green(" To fix, run:")),t.push(le.default.green.bold(" badgerclaw setup")),t.push(""),t.push(le.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
3
+ `)}async function An(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=Ns(e);if(Ts(t))return;let o=await Os();if(!o)return;let n=Ls(o);n.length!==0&&(process.stderr.write(Ms(n)),process.exit(1))}var po,$t,ne,uo,le,Is,Rs,xs,Rn,As,Es,Ee=H(()=>{"use strict";po=u(require("fs")),$t=u(require("os")),ne=u(require("path")),uo=require("child_process"),le=u(require("chalk"));oe();Is=`${N}/api/v1/dashboard/versions/latest`,Rs=2500,xs=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),Rn=ne.default.join($t.default.homedir(),".openclaw/extensions/badgerclaw"),As=ne.default.join($t.default.homedir(),".openclaw/npm/node_modules/@badgerclaw/connect"),Es=ne.default.join($t.default.homedir(),".openclaw/npm/projects")});var Ln={};to(Ln,{HERMES_IMAGE_DEFAULT:()=>Pe,detectCapabilities:()=>ce,detectDiskFreeGb:()=>On,detectDocker:()=>Rt,detectHermes:()=>xt,detectOpenClaw:()=>Dn});function Rt(){if((0,et.spawnSync)("which",["docker"],{encoding:"utf-8"}).status!==0)return{installed:!1};let t=(0,et.spawnSync)("docker",["version","--format","{{.Server.Version}}"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout.trim()?{installed:!1}:{installed:!0,version:t.stdout.trim()}}function Dn(){let e=G();return e?{installed:!0,version:e}:{installed:!1}}function xt(e){if(!e.installed)return{installed:!1};let t=process.env.HERMES_IMAGE||Pe;return(0,et.spawnSync)("docker",["image","inspect","--format","{{.RepoDigests}}",t],{encoding:"utf-8",timeout:3e3}).status!==0?{installed:!1}:{installed:!0,image:t}}function On(){let e=Pn.default.join(fo.default.homedir(),".badgerclaw"),t=En.default.existsSync(e)?e:fo.default.homedir();if(process.platform==="win32")return null;let o=(0,et.spawnSync)("df",["-Pk",t],{encoding:"utf-8",timeout:3e3});if(o.status!==0||!o.stdout)return null;let n=o.stdout.trim().split(`
4
+ `);if(n.length<2)return null;let r=n[1].split(/\s+/),s=parseInt(r[3]||"",10);return Number.isFinite(s)?Math.floor(s/1024/1024):null}function ce(){let e=Rt();return{openclaw:Dn(),hermes:xt(e),docker:e,disk_free_gb:On(),ports_in_use:[]}}var et,En,fo,Pn,Pe,_e=H(()=>{"use strict";et=require("child_process"),En=u(require("fs")),fo=u(require("os")),Pn=u(require("path"));Ee();Pe="hermes-agent-bc:bundled"});function Et(e){return V.default.join(Bs,`bot-${e}`)}function jn(e){x.default.existsSync(Se)||x.default.mkdirSync(Se,{recursive:!0,mode:448}),x.default.writeFileSync(yo,JSON.stringify(e,null,2)+`
5
+ `,{mode:384})}function Hs(){if(!x.default.existsSync(yo))return null;try{let e=JSON.parse(x.default.readFileSync(yo,"utf-8"));return e&&e.provider==="ollama"?e:null}catch{return null}}function wo(e){return`badgerclaw-hermes-bot-${e}`}function bo(){if(!x.default.existsSync(ho))return{hermes_bots:{}};try{let e=x.default.readFileSync(ho,"utf-8"),t=JSON.parse(e);return{hermes_bots:t.hermes_bots&&typeof t.hermes_bots=="object"?t.hermes_bots:{}}}catch{return{hermes_bots:{}}}}function Us(e){x.default.existsSync(Se)||x.default.mkdirSync(Se,{recursive:!0,mode:448}),x.default.writeFileSync(ho,JSON.stringify(e,null,2)+`
6
+ `,{mode:384})}function Fs(e,t=js){let o=new Set(Object.values(e.hermes_bots).map(r=>r.port)),n=t;for(;o.has(n)||!Gs(n);)if(n+=1,n-t>1e3)throw new Error(`Could not find a free port near ${t} after 1000 tries \u2014 host is unusually busy`);return n}function Gs(e){let t=Mn.default.createServer(),o=!1;try{t.listen(e,"127.0.0.1"),o=!0}catch{o=!1}finally{try{t.close()}catch{}}return o}function Hn(e=process.env){let t=e.BADGERCLAW_LLM_PROVIDER?.toLowerCase(),o=e.BADGERCLAW_LLM_API_KEY;if(t==="ollama")return{provider:"ollama",apiKey:"",baseUrl:e.BADGERCLAW_LLM_BASE_URL||At,model:e.BADGERCLAW_LLM_MODEL||void 0};if(t&&o){if(t!=="gemini"&&t!=="anthropic"&&t!=="openrouter")throw new Error(`BADGERCLAW_LLM_PROVIDER must be one of: gemini, anthropic, openrouter, ollama. Got '${t}'.`);return{provider:t,apiKey:o}}let n=Hs();if(n)return{provider:"ollama",apiKey:"",baseUrl:n.base_url||At,model:n.model||void 0};let r=e.GOOGLE_API_KEY||e.GEMINI_API_KEY;if(r)return{provider:"gemini",apiKey:r};if(e.ANTHROPIC_API_KEY)return{provider:"anthropic",apiKey:e.ANTHROPIC_API_KEY};if(e.OPENROUTER_API_KEY)return{provider:"openrouter",apiKey:e.OPENROUTER_API_KEY}}function _o(e){switch(e){case"gemini":return"gemini-2.5-flash";case"anthropic":return"claude-sonnet-4-6";case"openrouter":return"anthropic/claude-sonnet-4-6";case"ollama":return"qwen2.5:3b"}}function Ws(e){switch(e){case"gemini":return"GOOGLE_API_KEY";case"anthropic":return"ANTHROPIC_API_KEY";case"openrouter":return"OPENROUTER_API_KEY";case"ollama":return"OPENAI_API_KEY"}}function qs(e,t){let o=[`# Generated by badgerclaw CLI for bot ${e.botId}.`,"# Edit at your own risk; subsequent pair operations may overwrite.","",`MATRIX_HOMESERVER=${e.matrixHomeserver}`,`MATRIX_ACCESS_TOKEN=${e.matrixAccessToken}`,`MATRIX_USER_ID=${e.matrixUserId}`,`MATRIX_DEVICE_ID=${e.matrixDeviceId}`,"MATRIX_ENCRYPTION=true",`MATRIX_ALLOWED_USERS=${e.ownerMatrixUserId}`];return e.homeRoomId&&o.push(`MATRIX_HOME_ROOM=${e.homeRoomId}`),e.llm&&(o.push(""),e.llm.provider==="ollama"?(o.push("# Local Ollama (OpenAI-compatible) \u2014 no real API key needed."),o.push(`OPENAI_BASE_URL=${e.llm.baseUrl||At}`),o.push("OPENAI_API_KEY=ollama")):(o.push("# LLM provider \u2014 set by the operator's environment at pair time."),o.push("# Hermes reads this directly; model selection lives in config.yaml."),o.push(`${Ws(e.llm.provider)}=${e.llm.apiKey}`))),o.push("","# OpenAI-compatible API surface \u2014 localhost only by default so the","# CLI's daemon can health-check the container without exposing it","# beyond the host loopback.","API_SERVER_ENABLED=true","API_SERVER_HOST=127.0.0.1",`API_SERVER_PORT=${t}`,`API_SERVER_KEY=${(0,Tn.randomBytes)(24).toString("hex")}`),o.join(`
6
7
  `)+`
7
- `}function Ts(e){let t=[`# Hermes agent config for BadgerClaw bot ${e.botId}.`,"# Generated by badgerclaw CLI; secrets live in the sibling .env file.",""];return e.llm&&t.push("model:",` default: ${Ds(e.llm.provider)}`,` provider: ${e.llm.provider}`,""),t.push("agent:",` name: ${e.botName||"BadgerClaw bot"}`,"terminal:"," backend: local","subagents:"," max_spawn_depth: 1","cron:"," enabled: false",""),t.join(`
8
- `)}function Ls(e){return[`# ${e.botName||"BadgerClaw bot"}`,"","You are a helpful assistant connected to the BadgerClaw platform via Matrix.","Respond concisely. Honour @mentions. Decline to act on rooms you weren't added to.",""].join(`
9
- `)}function Bs(e,t){let o=Rt(e.botId);N.default.mkdirSync(o,{recursive:!0,mode:448});let n=Z.default.join(o,".env"),r=Z.default.join(o,"config.yaml"),s=Z.default.join(o,"SOUL.md");return N.default.writeFileSync(n,Ns(e,t),{mode:384}),N.default.writeFileSync(r,Ts(e),{mode:384}),N.default.existsSync(s)||N.default.writeFileSync(s,Ls(e),{mode:384}),{dataDir:o,envPath:n,configPath:r,soulPath:s}}function Et(e){let t=e.run(["network","inspect","bridge","--format","{{range .IPAM.Config}}{{.Subnet}} {{end}}"]);return t.status===0&&!!(t.stdout||"").trim()}function wo(e={}){let t=e.env??process.env;return t.BADGERCLAW_HERMES_NETWORK==="host"?!0:t.BADGERCLAW_HERMES_NETWORK==="bridge"?!1:!(e.bridgeUsable??(()=>Et(At)))()}function js(e){let t=process.getuid?.()??0,o=process.getgid?.()??0,n=["run","-d","--name",e.containerName,"--restart","unless-stopped","-v",`${e.dataDir}:/opt/data`];return e.hostNetwork??process.env.BADGERCLAW_HERMES_NETWORK==="host"?n.push("--network","host"):n.push("-p",`127.0.0.1:${e.port}:${e.port}`),t>0&&n.push("-e",`HERMES_UID=${t}`),o>0&&n.push("-e",`HERMES_GID=${o}`),n.push("--env-file",`${e.dataDir}/.env`,e.image,"gateway","run"),n}function Ln(e,t={}){let o=t.docker??At,n=e.image||process.env.HERMES_IMAGE||Ee;e.llm||console.warn(`[hermes] no LLM provider configured for bot ${e.botId}. Set BADGERCLAW_LLM_PROVIDER + BADGERCLAW_LLM_API_KEY (or one of GOOGLE_API_KEY / ANTHROPIC_API_KEY / OPENROUTER_API_KEY) and re-pair, or the bot will join rooms but be unable to reply.`);let r=yo(),s=r.hermes_bots[e.botId],a=s?.port??Es(r,t.portBase),c=s?.container_name??ho(e.botId);if(Bs(e,a),!t.skipDocker){o.run(["rm","-f",c]);let l=wo({bridgeUsable:()=>Et(o)}),m=js({containerName:c,dataDir:Rt(e.botId),port:a,image:n,hostNetwork:l}),p=o.run(m);if(p.status!==0)throw new Error(`docker run failed (exit ${p.status}): ${p.stderr||p.stdout}`)}let i={bot_id:e.botId,runtime:"hermes",container_name:c,port:a,data_dir:Rt(e.botId),image:n,started_at:new Date().toISOString()};return r.hermes_bots[e.botId]=i,As(r),i}function bo(e={}){let t=e.docker??At,o=yo(),n=[];for(let[r,s]of Object.entries(o.hermes_bots)){let a=t.run(["inspect","--format","{{.State.Status}}",s.container_name]),c,i=a.stdout.trim()||null;a.status!==0?(c="missing",i=(a.stderr||a.stdout).trim()||null):i==="running"?c="running":i==="exited"||i==="dead"||i==="created"?c="stopped":c="unknown",n.push({bot_id:r,container_name:s.container_name,status:c,raw:i})}return n}function Bn(e={}){return bo(e).map(o=>({bot_id:o.bot_id,bot_username:"",status:o.status==="running"?"running":o.status==="missing"?"error":"stopped",activity_state:"idle",active_task:null,last_activity_at:null,messages_received:0,messages_sent:0,chunked_messages:0,total_chunks_sent:0,errors:o.status==="missing"?1:0,last_error:o.status==="missing"?o.raw||"container missing":null,last_error_at:null,uptime_seconds:0,rooms_active:0,room_details:[],claude_code_enabled:!1,claude_code_session_id:null,quarantined:!1}))}function Hs(e){let t=e.match(Ms);return t?t[1].trim():null}async function _o(e,t,o,n={}){let r={recoveryKey:null,posted:!1,envUpdated:!1};if(!e.backendBotId)return r;let a=(n.docker??At).run(["logs",t]),c=`${a.stdout}
10
- ${a.stderr}`,i=Hs(c);if(!i)return r;if(r.recoveryKey=i,n.api)try{let m=await n.api.post(`/api/v1/hermes/bots/${e.backendBotId}/runtime-bootstrap`,{recovery_key:i,image_ref:o});r.posted=m.status>=200&&m.status<300}catch(m){console.warn(`[hermes] failed to POST recovery key for ${e.botId}: ${m.message}. Daemon will retry next beat.`)}let l=n.envPath??Z.default.join(Rt(e.botId),".env");return N.default.existsSync(l)&&(N.default.readFileSync(l,"utf-8").includes("MATRIX_RECOVERY_KEY=")||(N.default.appendFileSync(l,`
8
+ `}function Vs(e){let t=[`# Hermes agent config for BadgerClaw bot ${e.botId}.`,"# Generated by badgerclaw CLI; secrets live in the sibling .env file.",""];if(e.llm){let o=e.llm.model||_o(e.llm.provider);t.push("model:",` default: ${o}`,` provider: ${e.llm.provider}`),e.llm.provider==="ollama"&&t.push(` base_url: ${e.llm.baseUrl||At}`," ollama_num_ctx: 65536"),t.push("")}return t.push("agent:",` name: ${e.botName||"BadgerClaw bot"}`,"terminal:"," backend: local","subagents:"," max_spawn_depth: 1","cron:"," enabled: false",""),t.join(`
9
+ `)}function Ks(e){return[`# ${e.botName||"BadgerClaw bot"}`,"","You are a helpful assistant connected to the BadgerClaw platform via Matrix.","Respond concisely. Honour @mentions. Decline to act on rooms you weren't added to.",""].join(`
10
+ `)}function Ys(e,t){let o=Et(e.botId);x.default.mkdirSync(o,{recursive:!0,mode:448});let n=V.default.join(o,".env"),r=V.default.join(o,"config.yaml"),s=V.default.join(o,"SOUL.md");return x.default.writeFileSync(n,qs(e,t),{mode:384}),x.default.writeFileSync(r,Vs(e),{mode:384}),x.default.existsSync(s)||x.default.writeFileSync(s,Ks(e),{mode:384}),{dataDir:o,envPath:n,configPath:r,soulPath:s}}function Dt(e){let t=e.run(["network","inspect","bridge","--format","{{range .IPAM.Config}}{{.Subnet}} {{end}}"]);return t.status===0&&!!(t.stdout||"").trim()}function So(e={}){let t=e.env??process.env;return t.BADGERCLAW_HERMES_NETWORK==="host"?!0:t.BADGERCLAW_HERMES_NETWORK==="bridge"?!1:!(e.bridgeUsable??(()=>Dt(Pt)))()}function Js(e){let t=process.getuid?.()??0,o=process.getgid?.()??0,n=["run","-d","--name",e.containerName,"--restart","unless-stopped","-v",`${e.dataDir}:/opt/data`];return e.hostNetwork??process.env.BADGERCLAW_HERMES_NETWORK==="host"?n.push("--network","host"):n.push("-p",`127.0.0.1:${e.port}:${e.port}`),t>0&&n.push("-e",`HERMES_UID=${t}`),o>0&&n.push("-e",`HERMES_GID=${o}`),n.push("--env-file",`${e.dataDir}/.env`,e.image,"gateway","run"),n}function Un(e,t={}){let o=t.docker??Pt,n=e.image||process.env.HERMES_IMAGE||Pe;e.llm||console.warn(`[hermes] no LLM provider configured for bot ${e.botId}. Set BADGERCLAW_LLM_PROVIDER + BADGERCLAW_LLM_API_KEY (or one of GOOGLE_API_KEY / ANTHROPIC_API_KEY / OPENROUTER_API_KEY) and re-pair, or the bot will join rooms but be unable to reply.`);let r=bo(),s=r.hermes_bots[e.botId],a=s?.port??Fs(r,t.portBase),c=s?.container_name??wo(e.botId);if(Ys(e,a),!t.skipDocker){o.run(["rm","-f",c]);let i=So({bridgeUsable:()=>Dt(o)}),m=Js({containerName:c,dataDir:Et(e.botId),port:a,image:n,hostNetwork:i}),p=o.run(m);if(p.status!==0)throw new Error(`docker run failed (exit ${p.status}): ${p.stderr||p.stdout}`)}let l={bot_id:e.botId,runtime:"hermes",container_name:c,port:a,data_dir:Et(e.botId),image:n,started_at:new Date().toISOString()};return r.hermes_bots[e.botId]=l,Us(r),l}function ko(e={}){let t=e.docker??Pt,o=bo(),n=[];for(let[r,s]of Object.entries(o.hermes_bots)){let a=t.run(["inspect","--format","{{.State.Status}}",s.container_name]),c,l=a.stdout.trim()||null;a.status!==0?(c="missing",l=(a.stderr||a.stdout).trim()||null):l==="running"?c="running":l==="exited"||l==="dead"||l==="created"?c="stopped":c="unknown",n.push({bot_id:r,container_name:s.container_name,status:c,raw:l})}return n}function Fn(e={}){return ko(e).map(o=>({bot_id:o.bot_id,bot_username:"",status:o.status==="running"?"running":o.status==="missing"?"error":"stopped",activity_state:"idle",active_task:null,last_activity_at:null,messages_received:0,messages_sent:0,chunked_messages:0,total_chunks_sent:0,errors:o.status==="missing"?1:0,last_error:o.status==="missing"?o.raw||"container missing":null,last_error_at:null,uptime_seconds:0,rooms_active:0,room_details:[],claude_code_enabled:!1,claude_code_session_id:null,quarantined:!1}))}function Xs(e){let t=e.match(zs);return t?t[1].trim():null}async function vo(e,t,o,n={}){let r={recoveryKey:null,posted:!1,envUpdated:!1};if(!e.backendBotId)return r;let a=(n.docker??Pt).run(["logs",t]),c=`${a.stdout}
11
+ ${a.stderr}`,l=Xs(c);if(!l)return r;if(r.recoveryKey=l,n.api)try{let m=await n.api.post(`/api/v1/hermes/bots/${e.backendBotId}/runtime-bootstrap`,{recovery_key:l,image_ref:o});r.posted=m.status>=200&&m.status<300}catch(m){console.warn(`[hermes] failed to POST recovery key for ${e.botId}: ${m.message}. Daemon will retry next beat.`)}let i=n.envPath??V.default.join(Et(e.botId),".env");return x.default.existsSync(i)&&(x.default.readFileSync(i,"utf-8").includes("MATRIX_RECOVERY_KEY=")||(x.default.appendFileSync(i,`
11
12
  # Cross-signing recovery key captured from first-boot logs.
12
13
  # Hermes re-uses this on restart to re-sign the device after
13
14
  # Synapse rotates server keys.
14
- MATRIX_RECOVERY_KEY=${i}
15
- `),r.envUpdated=!0)),r}async function jn(e={}){let t=yo(),o=[];for(let[n,r]of Object.entries(t.hermes_bots)){let s=Z.default.join(r.data_dir,".env"),a=!1;try{N.default.existsSync(s)&&(a=N.default.readFileSync(s,"utf-8").includes("MATRIX_RECOVERY_KEY="))}catch{}if(a){o.push({bot_id:n,attempted:!1,recoveryKeyFound:!0,posted:!1,envUpdated:!1});continue}if(n.startsWith("@")){o.push({bot_id:n,attempted:!1,recoveryKeyFound:!1,posted:!1,envUpdated:!1});continue}try{let c=await _o({botId:n,backendBotId:n},r.container_name,r.image,{docker:e.docker,api:e.api,envPath:s});o.push({bot_id:n,attempted:!0,recoveryKeyFound:c.recoveryKey!==null,posted:c.posted,envUpdated:c.envUpdated})}catch(c){console.warn(`[hermes] recovery-key retry failed for ${n}: ${c.message}`),o.push({bot_id:n,attempted:!0,recoveryKeyFound:!1,posted:!1,envUpdated:!1})}}return o}var Pn,Dn,N,On,Nn,Z,xt,xs,fo,Rs,At,Ms,Pt=M(()=>{"use strict";Pn=require("child_process"),Dn=require("crypto"),N=d(require("fs")),On=d(require("net")),Nn=d(require("os")),Z=d(require("path"));_e();xt=Z.default.join(Nn.default.homedir(),".badgerclaw"),xs=Z.default.join(xt,"hermes"),fo=Z.default.join(xt,"state.json"),Rs=8642,At={run:e=>{let t=(0,Pn.spawnSync)("docker",e,{encoding:"utf-8"});return{status:t.status,stdout:t.stdout||"",stderr:t.stderr||""}}};Ms=/SAVE THIS RECOVERY KEY[\s\S]*?key rotation:\s+((?:[A-Za-z0-9]{4}\s+){7,}[A-Za-z0-9]{4})/});function Dt(e){return`'${e.replace(/'/g,"'\\''")}'`}function Us(){if(de!==null)return de;let e=["/opt/homebrew/lib/node_modules/openclaw/openclaw.mjs","/usr/local/lib/node_modules/openclaw/openclaw.mjs","/usr/lib/node_modules/openclaw/openclaw.mjs"];for(let t of e)if(Ze.default.existsSync(t))return de=`${Dt(process.execPath)} ${Dt(t)}`,de;try{let{execSync:t}=require("child_process"),o=t("npm root -g",{encoding:"utf-8",timeout:5e3,stdio:["ignore","pipe","ignore"]}).toString().trim();if(o){let n=vo.default.join(o,"openclaw","openclaw.mjs");if(Ze.default.existsSync(n))return de=`${Dt(process.execPath)} ${Dt(n)}`,de}}catch{}return de="openclaw",de}function So(e,t,o){t?t.fail(V.default.red(o)):e&&console.error(`[autopair] ${o}`)}async function Fs(e){if(!e.owner_matrix_user_id)throw new Error("Hermes redeem response missing owner_matrix_user_id. Update the API or fall back to OpenClaw runtime for this bot.");let t=e.user_id.replace(/[^a-zA-Z0-9_.-]/g,"_"),o={botId:e.bot_id??t,backendBotId:e.bot_id??void 0,matrixHomeserver:e.homeserver,matrixAccessToken:e.access_token,matrixUserId:e.user_id,matrixDeviceId:e.device_id,ownerMatrixUserId:e.owner_matrix_user_id,botName:e.bot_name,llm:Tn()},n=Ln(o);if(o.backendBotId){let r=_();if(r){let s=ze(r.access_token);try{await _o(o,ho(o.botId),n.image,{api:{post:async(a,c)=>{let i=await s.post(a,c);return{status:i.status,data:i.data}}}})}catch(a){console.warn(`[hermes] recovery key capture failed for ${o.botId}: ${a.message}. Daemon will retry next beat.`)}}}}async function et(e,t,o,n){let r=_();if(!r)return;let s=n?null:(0,ko.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${H}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e,instance_id:Q()})});if(!a.ok){if(a.status===410){s?.info(V.default.dim(`${t} already paired (race-loss; another channel redeemed first).`));return}let m=await a.json().catch(()=>({errors:[a.statusText]}));So(n,s,`Failed to redeem ${t}: ${m.errors?.[0]||a.status}`);return}let c=await a.json(),i=c.result??c;if((i.runtime??"openclaw")==="hermes"){try{await Fs(i),s?.succeed(V.default.green(`\u2705 ${i.bot_name} (${i.user_id}) running on Hermes \u2014 bot is live!`))}catch(m){So(n,s,`Failed to start Hermes container for ${t}: ${m.message}`)}return}await kn(async()=>{let m=i.user_id.split(":")[0].replace("@","").replace(/_bot$/,""),p;try{p=JSON.parse(Ze.default.readFileSync(Mn,"utf-8"))}catch{p={}}p.channels||(p.channels={}),p.channels.badgerclaw||(p.channels.badgerclaw={}),p.channels.badgerclaw.accounts||(p.channels.badgerclaw.accounts={});let E={userId:i.user_id,accessToken:i.access_token,homeserver:i.homeserver,encryption:!0,groupPolicy:"open",allowlistOnly:!1,dm:{policy:"open"}};i.device_id&&(E.deviceId=i.device_id),p.channels.badgerclaw.accounts[m]=E,Ze.default.writeFileSync(Mn,JSON.stringify(p,null,2),{mode:384})}),await fetch(`${H}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${r.access_token}`}}).catch(()=>{}),s?.succeed(V.default.green(`\u2705 ${i.bot_name} (${i.user_id}) paired \u2014 bot is live!`))}catch(a){So(n,s,`Failed to pair ${t}: ${a.message}`)}}async function tt(e=!1){let t=_();if(!t)return 0;let o=ze(t.access_token);try{let{data:n}=await o.get("/api/v1/openclaw/pending-pairs");if(!n||n.length===0)return 0;let r=new Map;for(let a of n)r.set(a.bot_user_id,a);for(let a of n)r.get(a.bot_user_id)!==a&&await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{});let s=0;for(let a of r.values()){let c=e?null:(0,ko.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await et(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),s++}catch(i){c?.fail(V.default.red(`Error pairing ${a.bot_name}: ${i}`))}}if(s>0)try{let{execSync:a}=await import("child_process");a(`${Us()} gateway restart`,{stdio:"ignore"}),e||console.log(V.default.green(`
16
- \u26A1 ${s} bot(s) paired \u2014 gateway restarted, bots are live!`))}catch(a){e?console.error(`[autopair] gateway restart after pair failed: ${a?.message||a}`):console.log(V.default.yellow(`
17
- \u26A1 ${s} bot(s) paired. Run: openclaw gateway restart`))}return s}catch{return 0}}var Hn,V,ko,Un,vo,Ze,Mn,de,Fn,ot=M(()=>{"use strict";Hn=require("commander"),V=d(require("chalk")),ko=d(require("ora")),Un=d(require("os")),vo=d(require("path")),Ze=d(require("fs"));L();he();ae();xe();Xe();Pt();Mn=vo.default.join(Un.default.homedir(),".openclaw","openclaw.json");de=null;Fn=new Hn.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!_()){console.log(V.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(V.default.dim("Checking for pending bot pairs...")),await tt(!1)===0&&console.log(V.default.dim("No pending pairs found."))})});async function Eo(){try{return await Lt.default.get(ia,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function at(){try{let t=(await Lt.default.get(`${er}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(Ao=t.pluginVersion),t}catch{return{status:await Eo()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:Ao,bots:[]}}}function Po(e){e&&e!=="unknown"&&(Ao=e)}async function Le(){try{return{success:!0,message:(await Lt.default.post(`${er}/restart`,{},{timeout:15e3})).data?.message||"Gateway restart initiated"}}catch(e){try{let{execSync:t}=await import("child_process");return t("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted via CLI fallback"}}catch{return{success:!1,message:e.message||"Failed to restart gateway"}}}}var Lt,sa,er,aa,ia,Ao,ue=M(()=>{"use strict";Lt=d(require("axios")),sa=7331,er=`http://localhost:${sa}`,aa=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,ia=`http://127.0.0.1:${aa}`,Ao="unknown"});var Go={};eo(Go,{getActiveSessions:()=>Fo,launchClaudeCode:()=>Mo,launchMCPServer:()=>jo,recordSession:()=>Ho,stopSession:()=>Uo});function No(){try{if(B.default.existsSync(Oo))return JSON.parse(B.default.readFileSync(Oo,"utf-8"))}catch{}return[]}function To(e){B.default.mkdirSync(ve,{recursive:!0}),B.default.writeFileSync(Oo,JSON.stringify(e,null,2))}function Ht(e){try{return process.kill(e,0),!0}catch{return!1}}function ua(){if(process.env.TMUX)return"tmux";try{if((0,ne.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),B.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function Lo(e,t){let o=W.default.join(ve,`claude-launcher-${t}.exp`),n=W.default.join(ve,`pending-input-${t}.txt`);B.default.writeFileSync(n,"","utf-8");let r=`#!/usr/bin/expect -f
15
+ MATRIX_RECOVERY_KEY=${l}
16
+ `),r.envUpdated=!0)),r}async function Gn(e={}){let t=bo(),o=[];for(let[n,r]of Object.entries(t.hermes_bots)){let s=V.default.join(r.data_dir,".env"),a=!1;try{x.default.existsSync(s)&&(a=x.default.readFileSync(s,"utf-8").includes("MATRIX_RECOVERY_KEY="))}catch{}if(a){o.push({bot_id:n,attempted:!1,recoveryKeyFound:!0,posted:!1,envUpdated:!1});continue}if(n.startsWith("@")){o.push({bot_id:n,attempted:!1,recoveryKeyFound:!1,posted:!1,envUpdated:!1});continue}try{let c=await vo({botId:n,backendBotId:n},r.container_name,r.image,{docker:e.docker,api:e.api,envPath:s});o.push({bot_id:n,attempted:!0,recoveryKeyFound:c.recoveryKey!==null,posted:c.posted,envUpdated:c.envUpdated})}catch(c){console.warn(`[hermes] recovery-key retry failed for ${n}: ${c.message}`),o.push({bot_id:n,attempted:!0,recoveryKeyFound:!1,posted:!1,envUpdated:!1})}}return o}var Nn,Tn,x,Mn,Bn,V,Se,Bs,ho,js,At,Pt,yo,zs,De=H(()=>{"use strict";Nn=require("child_process"),Tn=require("crypto"),x=u(require("fs")),Mn=u(require("net")),Bn=u(require("os")),V=u(require("path"));_e();Se=V.default.join(Bn.default.homedir(),".badgerclaw"),Bs=V.default.join(Se,"hermes"),ho=V.default.join(Se,"state.json"),js=8642,At="http://127.0.0.1:11434/v1",Pt={run:e=>{let t=(0,Nn.spawnSync)("docker",e,{encoding:"utf-8"});return{status:t.status,stdout:t.stdout||"",stderr:t.stderr||""}}};yo=V.default.join(Se,"local-llm.json");zs=/SAVE THIS RECOVERY KEY[\s\S]*?key rotation:\s+((?:[A-Za-z0-9]{4}\s+){7,}[A-Za-z0-9]{4})/});function Ot(e){return`'${e.replace(/'/g,"'\\''")}'`}function Qs(){if(de!==null)return de;let e=["/opt/homebrew/lib/node_modules/openclaw/openclaw.mjs","/usr/local/lib/node_modules/openclaw/openclaw.mjs","/usr/lib/node_modules/openclaw/openclaw.mjs"];for(let t of e)if(tt.default.existsSync(t))return de=`${Ot(process.execPath)} ${Ot(t)}`,de;try{let{execSync:t}=require("child_process"),o=t("npm root -g",{encoding:"utf-8",timeout:5e3,stdio:["ignore","pipe","ignore"]}).toString().trim();if(o){let n=Io.default.join(o,"openclaw","openclaw.mjs");if(tt.default.existsSync(n))return de=`${Ot(process.execPath)} ${Ot(n)}`,de}}catch{}return de="openclaw",de}function $o(e,t,o){t?t.fail(K.default.red(o)):e&&console.error(`[autopair] ${o}`)}async function Zs(e){if(!e.owner_matrix_user_id)throw new Error("Hermes redeem response missing owner_matrix_user_id. Update the API or fall back to OpenClaw runtime for this bot.");let t=e.user_id.replace(/[^a-zA-Z0-9_.-]/g,"_"),o={botId:e.bot_id??t,backendBotId:e.bot_id??void 0,matrixHomeserver:e.homeserver,matrixAccessToken:e.access_token,matrixUserId:e.user_id,matrixDeviceId:e.device_id,ownerMatrixUserId:e.owner_matrix_user_id,botName:e.bot_name,llm:Hn()},n=Un(o);if(o.backendBotId){let r=b();if(r){let s=Qe(r.access_token);try{await vo(o,wo(o.botId),n.image,{api:{post:async(a,c)=>{let l=await s.post(a,c);return{status:l.status,data:l.data}}}})}catch(a){console.warn(`[hermes] recovery key capture failed for ${o.botId}: ${a.message}. Daemon will retry next beat.`)}}}}async function ot(e,t,o,n){let r=b();if(!r)return;let s=n?null:(0,Co.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${N}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e,instance_id:Z()})});if(!a.ok){if(a.status===410){s?.info(K.default.dim(`${t} already paired (race-loss; another channel redeemed first).`));return}let m=await a.json().catch(()=>({errors:[a.statusText]}));$o(n,s,`Failed to redeem ${t}: ${m.errors?.[0]||a.status}`);return}let c=await a.json(),l=c.result??c;if((l.runtime??"openclaw")==="hermes"){try{await Zs(l),s?.succeed(K.default.green(`\u2705 ${l.bot_name} (${l.user_id}) running on Hermes \u2014 bot is live!`))}catch(m){$o(n,s,`Failed to start Hermes container for ${t}: ${m.message}`)}return}await In(async()=>{let m=l.user_id.split(":")[0].replace("@","").replace(/_bot$/,""),p;try{p=JSON.parse(tt.default.readFileSync(Wn,"utf-8"))}catch{p={}}p.channels||(p.channels={}),p.channels.badgerclaw||(p.channels.badgerclaw={}),p.channels.badgerclaw.accounts||(p.channels.badgerclaw.accounts={});let P={userId:l.user_id,accessToken:l.access_token,homeserver:l.homeserver,encryption:!0,groupPolicy:"open",allowlistOnly:!1,dm:{policy:"open"}};l.device_id&&(P.deviceId=l.device_id),p.channels.badgerclaw.accounts[m]=P,tt.default.writeFileSync(Wn,JSON.stringify(p,null,2),{mode:384})}),await fetch(`${N}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${r.access_token}`}}).catch(()=>{}),s?.succeed(K.default.green(`\u2705 ${l.bot_name} (${l.user_id}) paired \u2014 bot is live!`))}catch(a){$o(n,s,`Failed to pair ${t}: ${a.message}`)}}async function nt(e=!1){let t=b();if(!t)return 0;let o=Qe(t.access_token);try{let{data:n}=await o.get("/api/v1/openclaw/pending-pairs");if(!n||n.length===0)return 0;let r=new Map;for(let a of n)r.set(a.bot_user_id,a);for(let a of n)r.get(a.bot_user_id)!==a&&await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{});let s=0;for(let a of r.values()){let c=e?null:(0,Co.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await ot(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),s++}catch(l){c?.fail(K.default.red(`Error pairing ${a.bot_name}: ${l}`))}}if(s>0)try{let{execSync:a}=await import("child_process");a(`${Qs()} gateway restart`,{stdio:"ignore"}),e||console.log(K.default.green(`
17
+ \u26A1 ${s} bot(s) paired \u2014 gateway restarted, bots are live!`))}catch(a){e?console.error(`[autopair] gateway restart after pair failed: ${a?.message||a}`):console.log(K.default.yellow(`
18
+ \u26A1 ${s} bot(s) paired. Run: openclaw gateway restart`))}return s}catch{return 0}}var qn,K,Co,Vn,Io,tt,Wn,de,Kn,rt=H(()=>{"use strict";qn=require("commander"),K=u(require("chalk")),Co=u(require("ora")),Vn=u(require("os")),Io=u(require("path")),tt=u(require("fs"));M();he();oe();xe();Ze();De();Wn=Io.default.join(Vn.default.homedir(),".openclaw","openclaw.json");de=null;Kn=new qn.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!b()){console.log(K.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(K.default.dim("Checking for pending bot pairs...")),await nt(!1)===0&&console.log(K.default.dim("No pending pairs found."))})});async function Oo(){try{return await Mt.default.get(wa,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function lt(){try{let t=(await Mt.default.get(`${sr}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(Do=t.pluginVersion),t}catch{return{status:await Oo()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:Do,bots:[]}}}function Lo(e){e&&e!=="unknown"&&(Do=e)}async function Be(){try{return{success:!0,message:(await Mt.default.post(`${sr}/restart`,{},{timeout:15e3})).data?.message||"Gateway restart initiated"}}catch(e){try{let{execSync:t}=await import("child_process");return t("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted via CLI fallback"}}catch{return{success:!1,message:e.message||"Failed to restart gateway"}}}}var Mt,ha,sr,ya,wa,Do,ue=H(()=>{"use strict";Mt=u(require("axios")),ha=7331,sr=`http://localhost:${ha}`,ya=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,wa=`http://127.0.0.1:${ya}`,Do="unknown"});var Vo={};to(Vo,{getActiveSessions:()=>qo,launchClaudeCode:()=>Fo,launchMCPServer:()=>Uo,recordSession:()=>Go,stopSession:()=>Wo});function Mo(){try{if(B.default.existsSync(To))return JSON.parse(B.default.readFileSync(To,"utf-8"))}catch{}return[]}function Bo(e){B.default.mkdirSync($e,{recursive:!0}),B.default.writeFileSync(To,JSON.stringify(e,null,2))}function Ut(e){try{return process.kill(e,0),!0}catch{return!1}}function ka(){if(process.env.TMUX)return"tmux";try{if((0,re.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),B.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function jo(e,t){let o=W.default.join($e,`claude-launcher-${t}.exp`),n=W.default.join($e,`pending-input-${t}.txt`);B.default.writeFileSync(n,"","utf-8");let r=`#!/usr/bin/expect -f
18
19
  set timeout -1
19
20
  set msgfile "${n}"
20
21
 
@@ -51,21 +52,21 @@ send "\\r"
51
52
  interact timeout 2 {
52
53
  check_and_send_messages
53
54
  }
54
- `;return B.default.mkdirSync(ve,{recursive:!0}),B.default.writeFileSync(o,r,{mode:493}),o}function Bo(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function ma(e,t,o){let n=Lo(e,o.BADGERCLAW_SESSION_ID||"default"),r=Bo(o),s=`
55
+ `;return B.default.mkdirSync($e,{recursive:!0}),B.default.writeFileSync(o,r,{mode:493}),o}function Ho(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function va(e,t,o){let n=jo(e,o.BADGERCLAW_SESSION_ID||"default"),r=Ho(o),s=`
55
56
  tell application "iTerm"
56
57
  activate
57
58
  set newWindow to (create window with default profile)
58
59
  tell current session of newWindow
59
- write text "cd ${Ut(t)} && ${r} && ${Ut(n)}"
60
+ write text "cd ${Ft(t)} && ${r} && ${Ft(n)}"
60
61
  end tell
61
62
  end tell
62
- `;(0,ne.execSync)(`osascript -e '${s.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function pa(e,t,o){let n=Lo(e,o.BADGERCLAW_SESSION_ID||"default"),r=Bo(o),a=`
63
+ `;(0,re.execSync)(`osascript -e '${s.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function $a(e,t,o){let n=jo(e,o.BADGERCLAW_SESSION_ID||"default"),r=Ho(o),a=`
63
64
  tell application "Terminal"
64
65
  activate
65
- do script "${`cd ${Ut(t)} && ${r} && ${Ut(n)}`.replace(/"/g,'\\"')}"
66
+ do script "${`cd ${Ft(t)} && ${r} && ${Ft(n)}`.replace(/"/g,'\\"')}"
66
67
  end tell
67
- `;(0,ne.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function ga(e,t,o){let n=Lo(e,o.BADGERCLAW_SESSION_ID||"default"),r=Bo(o),s=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${r} && ${n}`;(0,ne.execSync)(`tmux new-session -d -s ${s} "${a}"`,{stdio:"pipe",timeout:1e4})}function Ut(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function jo(e){let t=W.default.join(__dirname,"..","claude-code","mcp-server.js"),o=B.default.existsSync(t)?t:W.default.join(__dirname,"mcp-server.js"),n=(0,ne.spawn)("node",[o],{env:{...process.env,BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},cwd:e.projectDir,stdio:"ignore",detached:!0});return n.unref(),n}function Mo(e){let t=W.default.join(W.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=W.default.join(__dirname,"..","claude-code","mcp-server.js"),n=W.default.join(__dirname,"mcp-server.js"),r=B.default.existsSync(t)?t:B.default.existsSync(o)?o:n,s={BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},a=JSON.stringify({mcpServers:{badgerclaw:{command:"node",args:[r],env:s}}}),c=W.default.join(ve,`mcp-config-${e.sessionId}.json`);B.default.mkdirSync(ve,{recursive:!0}),B.default.writeFileSync(c,a,"utf-8");let i=`claude --dangerously-skip-permissions --mcp-config ${c}`;switch(ua()){case"iterm2":ma(i,e.projectDir,s);break;case"terminal":pa(i,e.projectDir,s);break;case"tmux":ga(i,e.projectDir,s);break;case"direct":(0,ne.spawn)(i,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...s},stdio:"ignore",detached:!0}).unref();break}}function Ho(e,t,o,n,r){let s=No().filter(a=>a.sessionId!==e);s.push({sessionId:e,pid:t,mcpPid:o,port:n,projectDir:r,startedAt:new Date().toISOString()}),To(s)}function Uo(e){let t=No(),o=t.find(r=>r.sessionId===e);if(!o)return!1;if(o.mcpPid&&Ht(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&Ht(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,ne.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let n=t.filter(r=>r.sessionId!==e);return To(n),!0}function Fo(){let e=No(),t=e.filter(o=>Ht(o.mcpPid)||Ht(o.pid));return t.length!==e.length&&To(t),t}var ne,B,W,nr,ve,Oo,Ft=M(()=>{"use strict";ne=require("child_process"),B=d(require("fs")),W=d(require("path")),nr=d(require("os")),ve=W.default.join(nr.default.homedir(),".badgerclaw"),Oo=W.default.join(ve,"claude-sessions.json")});async function re(e){return e.command_type==="update_cli"?ha(e.payload?.target_version):e.command_type==="update_plugin"?ya(e.payload?.target_version):e.command_type==="restart_gateway"?fa():e.command_type==="leave_room"?Da(e.payload):e.command_type==="start_claude_code"?va(e.payload):e.command_type==="stop_claude_code"?$a(e.payload):e.command_type==="start_claude_control"?Ca(e.payload):e.command_type==="stop_claude_control"?Ia(e.payload):e.command_type==="update_claude_tools"?xa(e.payload):e.command_type==="bot_share_notify"?Ra(e.payload):e.command_type==="bot_share_revoked"?Aa(e.payload):e.command_type==="bot_share_expired"?Ea(e.payload):e.command_type==="bot_refresh"?Pa(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function fa(){try{return(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,R.execSync)("curl -s -X POST http://localhost:7331/restart",{stdio:"pipe",timeout:1e4}).toString()}`}}catch(e){return{success:!1,message:`Gateway restart failed: ${e.message||"unknown error"}`}}}}function ha(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,R.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,R.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),r=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return ba(),{success:!0,message:`Updated CLI to ${r}`,newVersion:r}}catch(o){let n=o.stderr?.toString()||o.message||"Unknown error";return n.includes("EACCES")||n.includes("permission")?{success:!1,message:"Permission denied. Run: sudo npm install -g badgerclaw"}:{success:!1,message:`CLI update failed: ${n.slice(0,500)}`}}}async function ya(e){let t=$.default.join($e.default.homedir(),".openclaw","extensions","badgerclaw"),o=$.default.join($e.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),n=h.default.existsSync(o)?"npm":h.default.existsSync(t)?"legacy":null;if(n===null)return{success:!1,message:"Cannot find plugin install (checked ~/.openclaw/npm/node_modules/@badgerclaw/connect and ~/.openclaw/extensions/badgerclaw). Re-run: badgerclaw setup"};let r=e?`@badgerclaw/connect@${e}`:"@badgerclaw/connect@latest";try{if(n==="npm"){let m=$.default.dirname($.default.dirname($.default.dirname(o)));(0,R.execSync)(`npm install ${r}`,{cwd:m,stdio:"pipe",timeout:12e4});let p=$.default.join(o,"package.json"),E="unknown";h.default.existsSync(p)&&(E=JSON.parse(h.default.readFileSync(p,"utf-8")).version||"unknown"),Po(E);try{(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await rr(E)}let s=t;(0,R.execSync)(`npm install ${r}`,{cwd:s,stdio:"pipe",timeout:12e4});let a=$.default.join(s,"node_modules","@badgerclaw","connect"),c=$.default.join(a,"package.json"),i="unknown";h.default.existsSync(c)&&(i=JSON.parse(h.default.readFileSync(c,"utf-8")).version||"unknown"),Po(i),wa(a,s);let l=$.default.join(s,"package.json");if(h.default.existsSync(l)&&h.default.existsSync(c))try{let m=JSON.parse(h.default.readFileSync(l,"utf-8")),p=JSON.parse(h.default.readFileSync(c,"utf-8"));m.version=i,p.openclaw&&(m.openclaw={...m.openclaw,...p.openclaw}),h.default.writeFileSync(l,JSON.stringify(m,null,2)+`
68
- `)}catch{}try{(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await rr(i)}catch(s){return{success:!1,message:`Plugin update failed: ${(s.stderr?.toString()||s.message||"").slice(0,500)}`}}}async function rr(e){for(let t=0;t<15;t++){await new Promise(o=>setTimeout(o,1e3));try{let o=await j.default.get("http://localhost:7331/health",{timeout:3e3});if(o.data?.status==="running"&&o.data?.pluginVersion===e)break}catch{}}return{success:!0,message:`Updated plugin to ${e}, gateway restarted`,newVersion:e}}function wa(e,t){let o=$.default.join(e,"dist"),n=$.default.join(t,"dist");h.default.existsSync(o)&&(h.default.mkdirSync(n,{recursive:!0}),Wo(o,n));let r=$.default.join(e,"openclaw.plugin.json");h.default.existsSync(r)&&h.default.copyFileSync(r,$.default.join(t,"openclaw.plugin.json"));let s=$.default.join(e,"scripts"),a=$.default.join(t,"scripts");h.default.existsSync(s)&&(h.default.mkdirSync(a,{recursive:!0}),Wo(s,a));for(let c of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let i=$.default.join(t,c);h.default.existsSync(i)&&(h.default.statSync(i).isDirectory()?h.default.rmSync(i,{recursive:!0,force:!0}):h.default.unlinkSync(i))}}function Wo(e,t){for(let o of h.default.readdirSync(e,{withFileTypes:!0})){let n=$.default.join(e,o.name),r=$.default.join(t,o.name);o.isDirectory()?(h.default.mkdirSync(r,{recursive:!0}),Wo(n,r)):h.default.copyFileSync(n,r)}}function ba(){try{if(_a())return;try{(0,R.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,R.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,R.execSync)("sleep 1",{stdio:"pipe"});let e=(0,R.execSync)("command -v badgerclaw",{stdio:"pipe",shell:"/bin/sh"}).toString().trim()||"badgerclaw";(0,R.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,R.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function _a(){let e="";try{e=(0,R.execSync)("supervisorctl status badgerclaw-heartbeat 2>&1",{stdio:"pipe",shell:"/bin/sh",timeout:8e3}).toString()}catch(t){e=(t?.stdout?.toString()||"")+(t?.stderr?.toString()||"")}if(!e.includes("badgerclaw-heartbeat")||/no such process|ERROR/i.test(e))return!1;try{return(0,R.execSync)("nohup supervisorctl restart badgerclaw-heartbeat >/dev/null 2>&1 &",{stdio:"pipe",shell:"/bin/sh",timeout:8e3}),!0}catch{return!1}}function Sa(){let e=$.default.join($e.default.homedir(),".badgerclaw","workspace");h.default.mkdirSync(e,{recursive:!0});let t=$.default.join(e,".git");return h.default.existsSync(t)||(0,R.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),h.default.writeFileSync($.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
68
+ `;(0,re.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Ca(e,t,o){let n=jo(e,o.BADGERCLAW_SESSION_ID||"default"),r=Ho(o),s=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${r} && ${n}`;(0,re.execSync)(`tmux new-session -d -s ${s} "${a}"`,{stdio:"pipe",timeout:1e4})}function Ft(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Uo(e){let t=W.default.join(__dirname,"..","claude-code","mcp-server.js"),o=B.default.existsSync(t)?t:W.default.join(__dirname,"mcp-server.js"),n=(0,re.spawn)("node",[o],{env:{...process.env,BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},cwd:e.projectDir,stdio:"ignore",detached:!0});return n.unref(),n}function Fo(e){let t=W.default.join(W.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=W.default.join(__dirname,"..","claude-code","mcp-server.js"),n=W.default.join(__dirname,"mcp-server.js"),r=B.default.existsSync(t)?t:B.default.existsSync(o)?o:n,s={BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},a=JSON.stringify({mcpServers:{badgerclaw:{command:"node",args:[r],env:s}}}),c=W.default.join($e,`mcp-config-${e.sessionId}.json`);B.default.mkdirSync($e,{recursive:!0}),B.default.writeFileSync(c,a,"utf-8");let l=`claude --dangerously-skip-permissions --mcp-config ${c}`;switch(ka()){case"iterm2":va(l,e.projectDir,s);break;case"terminal":$a(l,e.projectDir,s);break;case"tmux":Ca(l,e.projectDir,s);break;case"direct":(0,re.spawn)(l,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...s},stdio:"ignore",detached:!0}).unref();break}}function Go(e,t,o,n,r){let s=Mo().filter(a=>a.sessionId!==e);s.push({sessionId:e,pid:t,mcpPid:o,port:n,projectDir:r,startedAt:new Date().toISOString()}),Bo(s)}function Wo(e){let t=Mo(),o=t.find(r=>r.sessionId===e);if(!o)return!1;if(o.mcpPid&&Ut(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&Ut(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,re.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let n=t.filter(r=>r.sessionId!==e);return Bo(n),!0}function qo(){let e=Mo(),t=e.filter(o=>Ut(o.mcpPid)||Ut(o.pid));return t.length!==e.length&&Bo(t),t}var re,B,W,lr,$e,To,Gt=H(()=>{"use strict";re=require("child_process"),B=u(require("fs")),W=u(require("path")),lr=u(require("os")),$e=W.default.join(lr.default.homedir(),".badgerclaw"),To=W.default.join($e,"claude-sessions.json")});async function se(e){return e.command_type==="update_cli"?Ra(e.payload?.target_version):e.command_type==="update_plugin"?xa(e.payload?.target_version):e.command_type==="restart_gateway"?Ia():e.command_type==="leave_room"?Ga(e.payload):e.command_type==="start_claude_code"?La(e.payload):e.command_type==="stop_claude_code"?Na(e.payload):e.command_type==="start_claude_control"?Ta(e.payload):e.command_type==="stop_claude_control"?Ma(e.payload):e.command_type==="update_claude_tools"?Ba(e.payload):e.command_type==="bot_share_notify"?ja(e.payload):e.command_type==="bot_share_revoked"?Ha(e.payload):e.command_type==="bot_share_expired"?Ua(e.payload):e.command_type==="bot_refresh"?Fa(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function Ia(){try{return(0,A.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,A.execSync)("curl -s -X POST http://localhost:7331/restart",{stdio:"pipe",timeout:1e4}).toString()}`}}catch(e){return{success:!1,message:`Gateway restart failed: ${e.message||"unknown error"}`}}}}function Ra(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,A.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,A.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),r=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return Ea(),{success:!0,message:`Updated CLI to ${r}`,newVersion:r}}catch(o){let n=o.stderr?.toString()||o.message||"Unknown error";return n.includes("EACCES")||n.includes("permission")?{success:!1,message:"Permission denied. Run: sudo npm install -g badgerclaw"}:{success:!1,message:`CLI update failed: ${n.slice(0,500)}`}}}async function xa(e){let t=$.default.join(Ce.default.homedir(),".openclaw","extensions","badgerclaw"),o=$.default.join(Ce.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),n=h.default.existsSync(o)?"npm":h.default.existsSync(t)?"legacy":null;if(n===null)return{success:!1,message:"Cannot find plugin install (checked ~/.openclaw/npm/node_modules/@badgerclaw/connect and ~/.openclaw/extensions/badgerclaw). Re-run: badgerclaw setup"};let r=e?`@badgerclaw/connect@${e}`:"@badgerclaw/connect@latest";try{if(n==="npm"){let m=$.default.dirname($.default.dirname($.default.dirname(o)));(0,A.execSync)(`npm install ${r}`,{cwd:m,stdio:"pipe",timeout:12e4});let p=$.default.join(o,"package.json"),P="unknown";h.default.existsSync(p)&&(P=JSON.parse(h.default.readFileSync(p,"utf-8")).version||"unknown"),Lo(P);try{(0,A.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await cr(P)}let s=t;(0,A.execSync)(`npm install ${r}`,{cwd:s,stdio:"pipe",timeout:12e4});let a=$.default.join(s,"node_modules","@badgerclaw","connect"),c=$.default.join(a,"package.json"),l="unknown";h.default.existsSync(c)&&(l=JSON.parse(h.default.readFileSync(c,"utf-8")).version||"unknown"),Lo(l),Aa(a,s);let i=$.default.join(s,"package.json");if(h.default.existsSync(i)&&h.default.existsSync(c))try{let m=JSON.parse(h.default.readFileSync(i,"utf-8")),p=JSON.parse(h.default.readFileSync(c,"utf-8"));m.version=l,p.openclaw&&(m.openclaw={...m.openclaw,...p.openclaw}),h.default.writeFileSync(i,JSON.stringify(m,null,2)+`
69
+ `)}catch{}try{(0,A.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await cr(l)}catch(s){return{success:!1,message:`Plugin update failed: ${(s.stderr?.toString()||s.message||"").slice(0,500)}`}}}async function cr(e){for(let t=0;t<15;t++){await new Promise(o=>setTimeout(o,1e3));try{let o=await j.default.get("http://localhost:7331/health",{timeout:3e3});if(o.data?.status==="running"&&o.data?.pluginVersion===e)break}catch{}}return{success:!0,message:`Updated plugin to ${e}, gateway restarted`,newVersion:e}}function Aa(e,t){let o=$.default.join(e,"dist"),n=$.default.join(t,"dist");h.default.existsSync(o)&&(h.default.mkdirSync(n,{recursive:!0}),Ko(o,n));let r=$.default.join(e,"openclaw.plugin.json");h.default.existsSync(r)&&h.default.copyFileSync(r,$.default.join(t,"openclaw.plugin.json"));let s=$.default.join(e,"scripts"),a=$.default.join(t,"scripts");h.default.existsSync(s)&&(h.default.mkdirSync(a,{recursive:!0}),Ko(s,a));for(let c of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let l=$.default.join(t,c);h.default.existsSync(l)&&(h.default.statSync(l).isDirectory()?h.default.rmSync(l,{recursive:!0,force:!0}):h.default.unlinkSync(l))}}function Ko(e,t){for(let o of h.default.readdirSync(e,{withFileTypes:!0})){let n=$.default.join(e,o.name),r=$.default.join(t,o.name);o.isDirectory()?(h.default.mkdirSync(r,{recursive:!0}),Ko(n,r)):h.default.copyFileSync(n,r)}}function Ea(){try{if(Pa())return;try{(0,A.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,A.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,A.execSync)("sleep 1",{stdio:"pipe"});let e=(0,A.execSync)("command -v badgerclaw",{stdio:"pipe",shell:"/bin/sh"}).toString().trim()||"badgerclaw";(0,A.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,A.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function Pa(){let e="";try{e=(0,A.execSync)("supervisorctl status badgerclaw-heartbeat 2>&1",{stdio:"pipe",shell:"/bin/sh",timeout:8e3}).toString()}catch(t){e=(t?.stdout?.toString()||"")+(t?.stderr?.toString()||"")}if(!e.includes("badgerclaw-heartbeat")||/no such process|ERROR/i.test(e))return!1;try{return(0,A.execSync)("nohup supervisorctl restart badgerclaw-heartbeat >/dev/null 2>&1 &",{stdio:"pipe",shell:"/bin/sh",timeout:8e3}),!0}catch{return!1}}function Da(){let e=$.default.join(Ce.default.homedir(),".badgerclaw","workspace");h.default.mkdirSync(e,{recursive:!0});let t=$.default.join(e,".git");return h.default.existsSync(t)||(0,A.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),h.default.writeFileSync($.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
69
70
 
70
71
  When you receive a message, it will be formatted like:
71
72
  [Room: RoomName] Sender: message text
@@ -74,14 +75,14 @@ Reply using the reply tool with botId="..." and roomId="..."
74
75
  ALWAYS use the \`reply\` MCP tool to send your response back to the chat room.
75
76
  Use the exact botId and roomId provided in the message \u2014 do not modify them.
76
77
  Keep responses concise and helpful.
77
- `),e}function ka(){try{h.default.mkdirSync($.default.dirname(Gt),{recursive:!0});try{let e=h.default.statSync(Gt);if(Date.now()-e.mtimeMs<6e4)return!1;h.default.unlinkSync(Gt)}catch{}return h.default.writeFileSync(Gt,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function va(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!ka())return{success:!0,message:"Claude Code start already in progress, skipping duplicate"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await it(e.bot_id),{launchClaudeCode:o,recordSession:n,getActiveSessions:r,stopSession:s}=(Ft(),nn(Go)),a=new Set;try{let E=(await j.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let D of E)if(D.botId!==t&&D.enabled!==!1){let f=D.port;typeof f=="number"&&f>=7332&&a.add(f)}}catch{}for(let p=7332;p<=7340;p++)try{(0,R.execSync)(`lsof -ti :${p} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(p)}catch{}let c=7332;for(;a.has(c);)c++;let i=r();for(let p of i)p.port===c&&(console.log(`[command-executor] Stopping existing session ${p.sessionId} on port ${c}`),s(p.sessionId));try{(0,R.execSync)(`lsof -ti :${c} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let l=e.session_id||`session-${Date.now()}`;await j.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:l,port:c},{timeout:1e4});let m=Sa();return o({sessionId:l,port:c,projectDir:m}),n(l,0,0,c,m),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${l}, port: ${c})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function it(e){if(e.startsWith("@"))return e;try{let o=(await j.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],n=$.default.join($e.default.homedir(),".badgerclaw","bot-mapping.json");if(h.default.existsSync(n)){let r=JSON.parse(h.default.readFileSync(n,"utf-8"));if(r[e])return r[e]}return o.length===1?o[0].botId:(console.warn(`[command-executor] Could not resolve bot UUID ${e} to Matrix ID, trying as-is`),e)}catch{return e}}async function $a(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await it(e.bot_id),o=e.session_id;if(!o)try{let n=await j.default.get("http://localhost:7331/claude-code/status",{timeout:5e3}),s=(n.data?.bots||n.data?.rooms||[]).find(a=>a.botId===t);s&&(o=s.sessionId)}catch{}if(await j.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:n}=(Ft(),nn(Go));n(o)}return{success:!0,message:"Claude Code stopped"}}catch(t){return{success:!1,message:`Failed to stop Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Ca(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;o.startsWith("@")||(o=await it(t));let n=e?.session_id||`cc-${Date.now()}`;return await j.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!0,sessionId:n,mode:"primary",tools:e?.tools},{timeout:1e4}),console.log(`[claude-control] Primary mode enabled for ${o} (session: ${n})`),{success:!0,message:`Claude Control (primary) started for ${o}`}}catch(t){return{success:!1,message:`Failed to start Claude Control: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Ia(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;return o.startsWith("@")||(o=await it(t)),await j.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!1},{timeout:1e4}),console.log(`[claude-control] Primary mode disabled for ${o}`),{success:!0,message:`Claude Control stopped for ${o}`}}catch(t){return{success:!1,message:`Failed to stop Claude Control: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function xa(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t||!e?.tools)return{success:!1,message:"Missing bot_id or tools in payload"};let o=t;return o.startsWith("@")||(o=await it(t)),await j.default.post("http://localhost:7331/claude-code/tools",{botId:o,tools:e.tools},{timeout:1e4}),{success:!0,message:`Tools updated for ${o}`}}catch(t){return{success:!1,message:`Failed to update tools: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Ra(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await j.default.post("http://localhost:7331/bot-share/notify",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,ownerDisplayName:e.owner_display_name||void 0,botDisplayName:e.bot_name||void 0,expiresAt:e.expires_at||void 0},{timeout:1e4}),console.log(`[bot-share] Notify: ${e.shared_with_user_id} can now access ${e.bot_user_id}`),{success:!0,message:`Share notification sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to notify share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Aa(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await j.default.post("http://localhost:7331/bot-share/revoked",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,botDisplayName:e.bot_name||void 0},{timeout:1e4}),console.log(`[bot-share] Revoked: ${e.shared_with_user_id} lost access to ${e.bot_user_id}`),{success:!0,message:`Share revocation sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to revoke share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Ea(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await j.default.post("http://localhost:7331/bot-share/expired",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,botDisplayName:e.bot_name||void 0},{timeout:1e4}),console.log(`[bot-share] Expired: ${e.shared_with_user_id} access to ${e.bot_user_id}`),{success:!0,message:`Share expiry sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to expire share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Pa(e){let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in bot_refresh payload"};let o=t;t.startsWith("@")&&(o=t.split(":")[0].replace("@","").replace(/_bot$/,""));let n=$.default.join($e.default.homedir(),".openclaw","badgerclaw","quarantine",`${o}.json`);try{h.default.rmSync(n,{force:!0})}catch{}try{return(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:`Bot ${o} quarantine cleared, gateway restarted`}}catch{return{success:!1,message:`Quarantine cleared for ${o} but gateway restart failed`}}}async function Da(e){if(!e?.bot_id||!e?.room_id)return{success:!1,message:"Missing bot_id or room_id in payload"};try{return{success:!0,message:(await j.default.post("http://localhost:7331/leave-room",{botId:e.bot_id,roomId:e.room_id},{timeout:15e3})).data?.message||"Left room"}}catch(t){return{success:!1,message:`Failed to leave room: ${t.response?.data?.message||t.message||"Unknown error"}`}}}var R,h,$,$e,j,Gt,qo=M(()=>{"use strict";R=require("child_process"),h=d(require("fs")),$=d(require("path")),$e=d(require("os")),j=d(require("axios"));ue();Gt=$.default.join($e.default.homedir(),".badgerclaw","claude-code.lock")});var Ko={};eo(Ko,{heartbeatCommand:()=>Vo,pushHeartbeat:()=>T});function qt(e,t){if(e!=="start_claude_code"&&e!=="stop_claude_code")return!1;let o=`${e}:${t||"unknown"}`,n=Date.now();for(let[r,s]of Wt)n-s>Ba&&Wt.delete(r);return Wt.has(o)?!0:(Wt.set(o,n),!1)}function ur(e,t){let o=bt(),n=e.bots.map(a=>({bot_id:a.botId,bot_username:a.botUsername,status:a.status,activity_state:a.activityState||"idle",active_task:a.activeTask||null,last_activity_at:a.lastActivity,messages_received:a.messagesReceived,messages_sent:a.messagesSent,chunked_messages:a.chunkedMessages,total_chunks_sent:a.totalChunksSent,errors:a.errors,last_error:a.lastError,last_error_at:a.lastErrorAt,uptime_seconds:a.uptimeSeconds,rooms_active:a.roomsActive,room_details:(a.roomDetails||[]).map(c=>({roomId:c.roomId,roomName:c.roomName,workspaceName:c.workspaceName||null,messagesInRoom:c.messagesInRoom,lastActivityInRoom:c.lastActivityInRoom})),claude_code_enabled:a.claudeCodeEnabled??!1,claude_code_session_id:a.claudeCodeSessionId??null,quarantined:a.quarantined??!1})),r=new Set(n.map(a=>a.bot_id)),s=Bn().filter(a=>!r.has(a.bot_id));return{instance_id:Q(),timestamp:new Date().toISOString(),cli_version:t,plugin_version:e.pluginVersion||"unknown",hostname:o.hostname,os:o.os,arch:o.arch,uptime_seconds:o.uptimeSeconds,mem_free_mb:o.memFreeMb,gateway_status:e.status,gateway_pid:e.pid,last_gateway_restart:e.lastRestart,capabilities:le(),hermes_containers:bo(),bots:[...n,...s]}}async function T(){let{version:e}=be(),t=await at(),o=ur(t,e);await O().post(dr,o)}function ja(e,t){if(!e||e.status!==t.status)return!0;let o=new Map(e.bots.map(n=>[n.botId,n]));for(let n of t.bots){let r=o.get(n.botId);if(!r||r.status!==n.status||r.errors!==n.errors)return!0}return e.bots.length!==t.bots.length}async function ir(){try{let o=(await O().get(Ta)).data?.shares||[],n={shares:o.map(r=>({botUserId:r.bot_user_id,sharedWithUserId:r.shared_with_user_id,expiresAt:r.expires_at||null,shareId:r.share_id}))};await lr.default.post("http://localhost:7331/bot-share/sync",n,{timeout:1e4}),console.log(g.default.dim(` [${C()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(g.default.dim(` [${C()}] Share sync failed (non-fatal): ${e.message}`))}}async function Ma(){if(!ar){ar=!0;try{await O().post(Na,{instance_id:Q()},{timeout:La}),console.log(g.default.dim(` [${new Date().toISOString()}] Posted disconnect \u2014 dashboard will mark machine offline immediately.`))}catch(e){console.log(g.default.dim(` [${new Date().toISOString()}] Disconnect post failed (non-fatal): ${e?.message||e}`))}}}async function mr(){let e=_();if(!e?.expires_at)return;let t=new Date(e.expires_at).getTime(),o=Date.now(),n=300*1e3;if(t-o<n)if(console.log(g.default.dim(` [${C()}] Token expires soon \u2014 refreshing proactively...`)),await so())console.log(g.default.green(` [${C()}] Token refreshed successfully`));else{let s=pn()||"unknown reason";console.log(g.default.yellow(` [${C()}] Token refresh failed: ${s}`))}}function Ua(e,t){let o=3e3,n=3e4,r=null;async function s(){try{await mr();let c=_()?.access_token||e,i=require("eventsource"),l=new i(`${H}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${c}`}});l.onopen=()=>{o=3e3,console.log(g.default.dim(` [${C()}] SSE connected \u2014 listening for real-time events`)),r&&clearTimeout(r),r=setTimeout(()=>{console.log(g.default.dim(` [${C()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),l.close(),s()},Ha)},l.onmessage=async m=>{try{let p=JSON.parse(m.data);await Fa(p)}catch{}},l.onerror=async()=>{l.close(),r&&(clearTimeout(r),r=null),console.log(g.default.dim(` [${C()}] SSE disconnected \u2014 reconnecting in ${o/1e3}s...`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}catch(a){console.log(g.default.dim(` [${C()}] SSE connection failed: ${a.message}`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}s()}function C(){return new Date().toISOString()}async function Fa(e){if(e.type==="pair"){console.log(g.default.cyan(` [${C()}] Pair event: ${e.bot_name}`)),await et(e.pair_code,e.bot_name,e.bot_user_id,!0);try{let{execSync:t}=await import("child_process");t("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(` [${C()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await T()}catch{}}else if(e.type==="bot.delete"&&e.bot_user_id){let t=e.bot_user_id,o=t.split(":")[0].replace("@","").replace(/_bot$/,"");console.log(g.default.yellow(` [${C()}] Bot deleted: ${t}`));try{let n=await import("fs"),r=await import("path"),s=await import("os"),a=r.join(s.homedir(),".openclaw","openclaw.json");if(we(()=>{let i=JSON.parse(n.readFileSync(a,"utf-8")),l=!1;if(i.channels?.badgerclaw?.accounts?.[o]&&(delete i.channels.badgerclaw.accounts[o],l=!0),i.agents?.list){let m=i.agents.list.length;i.agents.list=i.agents.list.filter(p=>p.id!==o),i.agents.list.length!==m&&(l=!0)}return l&&n.writeFileSync(a,JSON.stringify(i,null,2)),l})){console.log(g.default.green(` [${C()}] Removed "${o}" from openclaw.json`));let{execSync:i}=await import("child_process");try{i("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(` [${C()}] Gateway restarted`))}catch{}}}catch(n){console.log(g.default.red(` [${C()}] Failed to clean up bot: ${n}`))}try{await T()}catch{}}else if(e.type==="gateway-restart"){console.log(g.default.cyan(` [${C()}] Remote gateway-restart received`));let t=await Le();console.log(t.success?g.default.green(` [${C()}] Gateway restarted`):g.default.red(` [${C()}] Gateway restart failed: ${t.message}`));try{await T()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(g.default.cyan(` [${C()}] Claude Code START: bot=${e.bot_id}`)),qt("start_claude_code",e.bot_id)){console.log(g.default.dim(` [${C()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await re({id:e.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:e.bot_id,bot_user_id:e.bot_user_id,room_id:e.room_id,session_id:e.session_id}});e.command_id&&await O().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await T()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(g.default.cyan(` [${C()}] Claude Code STOP: bot=${e.bot_id}`)),qt("stop_claude_code",e.bot_id)){console.log(g.default.dim(` [${C()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await re({id:e.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:e.bot_id,bot_user_id:e.bot_user_id,room_id:e.room_id,session_id:e.session_id}});e.command_id&&await O().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await T()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(g.default.cyan(` [${C()}] Command: ${e.command_type} (${e.command_id})`)),qt(e.command_type,e.payload?.bot_id)){console.log(g.default.dim(` [${C()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=O();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await re({id:e.command_id,command_type:e.command_type,payload:e.payload});await t.post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:o.success?"success":"failed",result:o.message,new_version:o.newVersion||null}),e.command_type==="update_cli"&&o.success&&(console.log(g.default.cyan(` [${C()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await T()}catch{}}}var cr,g,lr,sr,Oa,dr,Na,Ta,La,ar,Wt,Ba,Vo,Ha,Be=M(()=>{"use strict";cr=require("commander"),g=d(require("chalk")),lr=d(require("axios"));L();he();xe();_e();Pt();ue();qo();ae();ot();ue();Xe();Ae();sr=3e4,Oa=15e4,dr="/api/v1/dashboard/heartbeat",Na="/api/v1/dashboard/disconnect",Ta="/api/v1/me/active-shares",La=3e3,ar=!1,Wt=new Map,Ba=3e4;Vo=new cr.Command("heartbeat").description("Run heartbeat daemon \u2014 reports telemetry to the BadgerClaw dashboard every 30s").action(async()=>{let e=_();e||(console.log(g.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=be();console.log(g.default.green(`Heartbeat daemon started (v${t})`)),console.log(g.default.dim(` Instance: ${Q()}`)),console.log(g.default.dim(` Interval: ${sr/1e3}s`)),console.log(g.default.dim(` Press Ctrl+C to stop.
78
- `));let o=null,n=10,r=0,s=async()=>{try{await mr();let i=await at(),l=ur(i,t);ja(o,i)&&o!==null&&console.log(g.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let p=O(),E=await p.post(dr,l);r=0;let D=i.bots.length,f=i.bots.filter(w=>w.status==="running").length;console.log(g.default.dim(` [${new Date().toISOString()}] gateway=${i.status} bots=${f}/${D} running mem=${l.mem_free_mb}MB free`)),o=i;try{let x=await jn({api:{post:async(z,qe)=>{let gt=await p.post(z,qe);return{status:gt.status,data:gt.data}}}});for(let z of x)z.attempted&&(z.posted||z.envUpdated)&&console.log(g.default.cyan(` [${new Date().toISOString()}] Hermes recovery key captured for ${z.bot_id} (posted=${z.posted}, env_updated=${z.envUpdated})`))}catch(w){console.log(g.default.dim(` [${new Date().toISOString()}] Hermes recovery-key retry skipped: ${w.message}`))}let v=E.data?.pending_commands||[],b=!1;for(let w of v)try{if(console.log(g.default.cyan(` [${new Date().toISOString()}] Received command: ${w.command_type} (${w.id})`)),await p.post(`/api/v1/dashboard/commands/${w.id}/ack`),qt(w.command_type,w.payload?.bot_id)){console.log(g.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${w.command_type}`));continue}let x=await re(w);console.log(x.success?g.default.green(` [${new Date().toISOString()}] ${x.message}`):g.default.red(` [${new Date().toISOString()}] ${x.message}`)),await p.post(`/api/v1/dashboard/commands/${w.id}/result`,{status:x.success?"success":"failed",result:x.message,new_version:x.newVersion||null}),w.command_type==="update_cli"&&x.success&&(b=!0)}catch(x){console.log(g.default.dim(` [${new Date().toISOString()}] Command ${w.id} error: ${x.message}`))}if(b){console.log(g.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await T()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(i){i instanceof Re&&(console.log(g.default.yellow(` [${new Date().toISOString()}] Account deactivated \u2014 signed out. Exiting daemon.`)),process.exit(0)),r+=1,console.log(g.default.dim(` [${new Date().toISOString()}] Heartbeat failed (${r}/${n}): ${i.message}`)),r>=n&&(console.log(g.default.red(` [${new Date().toISOString()}] ${n} consecutive heartbeat failures \u2014 exiting so launchctl/systemd can restart the daemon.`)),process.exit(1))}};await s();let a=G()!==null;a?await ir():console.log(g.default.dim(` [${C()}] Hermes-only host \u2014 share-sync disabled (no plugin to push to).`)),setInterval(s,sr),a&&setInterval(ir,Oa),Ua(e.access_token,t);let c=i=>{console.log(g.default.yellow(`
79
- [${new Date().toISOString()}] Received ${i} \u2014 posting disconnect and exiting.`)),Ma().finally(()=>{process.exit(0)})};process.on("SIGTERM",c),process.on("SIGINT",c),await new Promise(()=>{})});Ha=2700*1e3});var rs=require("commander");var pr=require("commander"),q=d(require("chalk")),gr=d(require("ora")),fr=d(require("open")),Jo=d(require("os"));var to=d(require("crypto"));function rn(){return to.default.randomBytes(32).toString("base64url")}function sn(e){return to.default.createHash("sha256").update(e).digest("base64url")}L();xe();he();ae();ot();var Nt=d(require("os")),J=d(require("fs")),Tt=d(require("path")),ke=require("child_process");var Pe=d(require("fs")),Se=d(require("path")),Oe=d(require("os")),Ne=require("child_process"),Gn="ai.badgerclaw.watch",Wn=Se.default.join(Oe.default.homedir(),"Library","LaunchAgents"),De=Se.default.join(Wn,`${Gn}.plist`);function Gs(){try{return(0,Ne.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function Ws(){try{return(0,Ne.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function qs(e){let t=Se.default.join(Oe.default.homedir(),".badgerclaw"),o=Ws(),n=Se.default.dirname(o),r=Se.default.dirname(e),s=[n,r,"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"],a=new Set,c=s.filter(i=>!i||a.has(i)?!1:(a.add(i),!0)).join(":");return`<?xml version="1.0" encoding="UTF-8"?>
78
+ `),e}function Oa(){try{h.default.mkdirSync($.default.dirname(Wt),{recursive:!0});try{let e=h.default.statSync(Wt);if(Date.now()-e.mtimeMs<6e4)return!1;h.default.unlinkSync(Wt)}catch{}return h.default.writeFileSync(Wt,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function La(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!Oa())return{success:!0,message:"Claude Code start already in progress, skipping duplicate"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await ct(e.bot_id),{launchClaudeCode:o,recordSession:n,getActiveSessions:r,stopSession:s}=(Gt(),ln(Vo)),a=new Set;try{let P=(await j.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let O of P)if(O.botId!==t&&O.enabled!==!1){let f=O.port;typeof f=="number"&&f>=7332&&a.add(f)}}catch{}for(let p=7332;p<=7340;p++)try{(0,A.execSync)(`lsof -ti :${p} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(p)}catch{}let c=7332;for(;a.has(c);)c++;let l=r();for(let p of l)p.port===c&&(console.log(`[command-executor] Stopping existing session ${p.sessionId} on port ${c}`),s(p.sessionId));try{(0,A.execSync)(`lsof -ti :${c} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let i=e.session_id||`session-${Date.now()}`;await j.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:i,port:c},{timeout:1e4});let m=Da();return o({sessionId:i,port:c,projectDir:m}),n(i,0,0,c,m),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${i}, port: ${c})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function ct(e){if(e.startsWith("@"))return e;try{let o=(await j.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],n=$.default.join(Ce.default.homedir(),".badgerclaw","bot-mapping.json");if(h.default.existsSync(n)){let r=JSON.parse(h.default.readFileSync(n,"utf-8"));if(r[e])return r[e]}return o.length===1?o[0].botId:(console.warn(`[command-executor] Could not resolve bot UUID ${e} to Matrix ID, trying as-is`),e)}catch{return e}}async function Na(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await ct(e.bot_id),o=e.session_id;if(!o)try{let n=await j.default.get("http://localhost:7331/claude-code/status",{timeout:5e3}),s=(n.data?.bots||n.data?.rooms||[]).find(a=>a.botId===t);s&&(o=s.sessionId)}catch{}if(await j.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:n}=(Gt(),ln(Vo));n(o)}return{success:!0,message:"Claude Code stopped"}}catch(t){return{success:!1,message:`Failed to stop Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Ta(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;o.startsWith("@")||(o=await ct(t));let n=e?.session_id||`cc-${Date.now()}`;return await j.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!0,sessionId:n,mode:"primary",tools:e?.tools},{timeout:1e4}),console.log(`[claude-control] Primary mode enabled for ${o} (session: ${n})`),{success:!0,message:`Claude Control (primary) started for ${o}`}}catch(t){return{success:!1,message:`Failed to start Claude Control: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Ma(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;return o.startsWith("@")||(o=await ct(t)),await j.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!1},{timeout:1e4}),console.log(`[claude-control] Primary mode disabled for ${o}`),{success:!0,message:`Claude Control stopped for ${o}`}}catch(t){return{success:!1,message:`Failed to stop Claude Control: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Ba(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t||!e?.tools)return{success:!1,message:"Missing bot_id or tools in payload"};let o=t;return o.startsWith("@")||(o=await ct(t)),await j.default.post("http://localhost:7331/claude-code/tools",{botId:o,tools:e.tools},{timeout:1e4}),{success:!0,message:`Tools updated for ${o}`}}catch(t){return{success:!1,message:`Failed to update tools: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function ja(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await j.default.post("http://localhost:7331/bot-share/notify",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,ownerDisplayName:e.owner_display_name||void 0,botDisplayName:e.bot_name||void 0,expiresAt:e.expires_at||void 0},{timeout:1e4}),console.log(`[bot-share] Notify: ${e.shared_with_user_id} can now access ${e.bot_user_id}`),{success:!0,message:`Share notification sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to notify share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Ha(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await j.default.post("http://localhost:7331/bot-share/revoked",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,botDisplayName:e.bot_name||void 0},{timeout:1e4}),console.log(`[bot-share] Revoked: ${e.shared_with_user_id} lost access to ${e.bot_user_id}`),{success:!0,message:`Share revocation sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to revoke share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Ua(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await j.default.post("http://localhost:7331/bot-share/expired",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,botDisplayName:e.bot_name||void 0},{timeout:1e4}),console.log(`[bot-share] Expired: ${e.shared_with_user_id} access to ${e.bot_user_id}`),{success:!0,message:`Share expiry sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to expire share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Fa(e){let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in bot_refresh payload"};let o=t;t.startsWith("@")&&(o=t.split(":")[0].replace("@","").replace(/_bot$/,""));let n=$.default.join(Ce.default.homedir(),".openclaw","badgerclaw","quarantine",`${o}.json`);try{h.default.rmSync(n,{force:!0})}catch{}try{return(0,A.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:`Bot ${o} quarantine cleared, gateway restarted`}}catch{return{success:!1,message:`Quarantine cleared for ${o} but gateway restart failed`}}}async function Ga(e){if(!e?.bot_id||!e?.room_id)return{success:!1,message:"Missing bot_id or room_id in payload"};try{return{success:!0,message:(await j.default.post("http://localhost:7331/leave-room",{botId:e.bot_id,roomId:e.room_id},{timeout:15e3})).data?.message||"Left room"}}catch(t){return{success:!1,message:`Failed to leave room: ${t.response?.data?.message||t.message||"Unknown error"}`}}}var A,h,$,Ce,j,Wt,Yo=H(()=>{"use strict";A=require("child_process"),h=u(require("fs")),$=u(require("path")),Ce=u(require("os")),j=u(require("axios"));ue();Wt=$.default.join(Ce.default.homedir(),".badgerclaw","claude-code.lock")});var zo={};to(zo,{heartbeatCommand:()=>Jo,pushHeartbeat:()=>T});function Vt(e,t){if(e!=="start_claude_code"&&e!=="stop_claude_code")return!1;let o=`${e}:${t||"unknown"}`,n=Date.now();for(let[r,s]of qt)n-s>Ya&&qt.delete(r);return qt.has(o)?!0:(qt.set(o,n),!1)}function hr(e,t){let o=St(),n=e.bots.map(a=>({bot_id:a.botId,bot_username:a.botUsername,status:a.status,activity_state:a.activityState||"idle",active_task:a.activeTask||null,last_activity_at:a.lastActivity,messages_received:a.messagesReceived,messages_sent:a.messagesSent,chunked_messages:a.chunkedMessages,total_chunks_sent:a.totalChunksSent,errors:a.errors,last_error:a.lastError,last_error_at:a.lastErrorAt,uptime_seconds:a.uptimeSeconds,rooms_active:a.roomsActive,room_details:(a.roomDetails||[]).map(c=>({roomId:c.roomId,roomName:c.roomName,workspaceName:c.workspaceName||null,messagesInRoom:c.messagesInRoom,lastActivityInRoom:c.lastActivityInRoom})),claude_code_enabled:a.claudeCodeEnabled??!1,claude_code_session_id:a.claudeCodeSessionId??null,quarantined:a.quarantined??!1})),r=new Set(n.map(a=>a.bot_id)),s=Fn().filter(a=>!r.has(a.bot_id));return{instance_id:Z(),timestamp:new Date().toISOString(),cli_version:t,plugin_version:e.pluginVersion||"unknown",hostname:o.hostname,os:o.os,arch:o.arch,uptime_seconds:o.uptimeSeconds,mem_free_mb:o.memFreeMb,gateway_status:e.status,gateway_pid:e.pid,last_gateway_restart:e.lastRestart,capabilities:ce(),hermes_containers:ko(),bots:[...n,...s]}}async function T(){let{version:e}=be(),t=await lt(),o=hr(t,e);await L().post(fr,o)}function Ja(e,t){if(!e||e.status!==t.status)return!0;let o=new Map(e.bots.map(n=>[n.botId,n]));for(let n of t.bots){let r=o.get(n.botId);if(!r||r.status!==n.status||r.errors!==n.errors)return!0}return e.bots.length!==t.bots.length}async function mr(){try{let o=(await L().get(Va)).data?.shares||[],n={shares:o.map(r=>({botUserId:r.bot_user_id,sharedWithUserId:r.shared_with_user_id,expiresAt:r.expires_at||null,shareId:r.share_id}))};await gr.default.post("http://localhost:7331/bot-share/sync",n,{timeout:1e4}),console.log(g.default.dim(` [${C()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(g.default.dim(` [${C()}] Share sync failed (non-fatal): ${e.message}`))}}async function za(){if(!ur){ur=!0;try{await L().post(qa,{instance_id:Z()},{timeout:Ka}),console.log(g.default.dim(` [${new Date().toISOString()}] Posted disconnect \u2014 dashboard will mark machine offline immediately.`))}catch(e){console.log(g.default.dim(` [${new Date().toISOString()}] Disconnect post failed (non-fatal): ${e?.message||e}`))}}}async function yr(){let e=b();if(!e?.expires_at)return;let t=new Date(e.expires_at).getTime(),o=Date.now(),n=300*1e3;if(t-o<n)if(console.log(g.default.dim(` [${C()}] Token expires soon \u2014 refreshing proactively...`)),await ao())console.log(g.default.green(` [${C()}] Token refreshed successfully`));else{let s=yn()||"unknown reason";console.log(g.default.yellow(` [${C()}] Token refresh failed: ${s}`))}}function Qa(e,t){let o=3e3,n=3e4,r=null;async function s(){try{await yr();let c=b()?.access_token||e,l=require("eventsource"),i=new l(`${N}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${c}`}});i.onopen=()=>{o=3e3,console.log(g.default.dim(` [${C()}] SSE connected \u2014 listening for real-time events`)),r&&clearTimeout(r),r=setTimeout(()=>{console.log(g.default.dim(` [${C()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),i.close(),s()},Xa)},i.onmessage=async m=>{try{let p=JSON.parse(m.data);await Za(p)}catch{}},i.onerror=async()=>{i.close(),r&&(clearTimeout(r),r=null),console.log(g.default.dim(` [${C()}] SSE disconnected \u2014 reconnecting in ${o/1e3}s...`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}catch(a){console.log(g.default.dim(` [${C()}] SSE connection failed: ${a.message}`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}s()}function C(){return new Date().toISOString()}async function Za(e){if(e.type==="pair"){console.log(g.default.cyan(` [${C()}] Pair event: ${e.bot_name}`)),await ot(e.pair_code,e.bot_name,e.bot_user_id,!0);try{let{execSync:t}=await import("child_process");t("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(` [${C()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await T()}catch{}}else if(e.type==="bot.delete"&&e.bot_user_id){let t=e.bot_user_id,o=t.split(":")[0].replace("@","").replace(/_bot$/,"");console.log(g.default.yellow(` [${C()}] Bot deleted: ${t}`));try{let n=await import("fs"),r=await import("path"),s=await import("os"),a=r.join(s.homedir(),".openclaw","openclaw.json");if(we(()=>{let l=JSON.parse(n.readFileSync(a,"utf-8")),i=!1;if(l.channels?.badgerclaw?.accounts?.[o]&&(delete l.channels.badgerclaw.accounts[o],i=!0),l.agents?.list){let m=l.agents.list.length;l.agents.list=l.agents.list.filter(p=>p.id!==o),l.agents.list.length!==m&&(i=!0)}return i&&n.writeFileSync(a,JSON.stringify(l,null,2)),i})){console.log(g.default.green(` [${C()}] Removed "${o}" from openclaw.json`));let{execSync:l}=await import("child_process");try{l("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(` [${C()}] Gateway restarted`))}catch{}}}catch(n){console.log(g.default.red(` [${C()}] Failed to clean up bot: ${n}`))}try{await T()}catch{}}else if(e.type==="gateway-restart"){console.log(g.default.cyan(` [${C()}] Remote gateway-restart received`));let t=await Be();console.log(t.success?g.default.green(` [${C()}] Gateway restarted`):g.default.red(` [${C()}] Gateway restart failed: ${t.message}`));try{await T()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(g.default.cyan(` [${C()}] Claude Code START: bot=${e.bot_id}`)),Vt("start_claude_code",e.bot_id)){console.log(g.default.dim(` [${C()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await se({id:e.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:e.bot_id,bot_user_id:e.bot_user_id,room_id:e.room_id,session_id:e.session_id}});e.command_id&&await L().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await T()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(g.default.cyan(` [${C()}] Claude Code STOP: bot=${e.bot_id}`)),Vt("stop_claude_code",e.bot_id)){console.log(g.default.dim(` [${C()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await se({id:e.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:e.bot_id,bot_user_id:e.bot_user_id,room_id:e.room_id,session_id:e.session_id}});e.command_id&&await L().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await T()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(g.default.cyan(` [${C()}] Command: ${e.command_type} (${e.command_id})`)),Vt(e.command_type,e.payload?.bot_id)){console.log(g.default.dim(` [${C()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=L();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await se({id:e.command_id,command_type:e.command_type,payload:e.payload});await t.post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:o.success?"success":"failed",result:o.message,new_version:o.newVersion||null}),e.command_type==="update_cli"&&o.success&&(console.log(g.default.cyan(` [${C()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await T()}catch{}}}var pr,g,gr,dr,Wa,fr,qa,Va,Ka,ur,qt,Ya,Jo,Xa,je=H(()=>{"use strict";pr=require("commander"),g=u(require("chalk")),gr=u(require("axios"));M();he();xe();_e();De();ue();Yo();oe();rt();ue();Ze();Ee();dr=3e4,Wa=15e4,fr="/api/v1/dashboard/heartbeat",qa="/api/v1/dashboard/disconnect",Va="/api/v1/me/active-shares",Ka=3e3,ur=!1,qt=new Map,Ya=3e4;Jo=new pr.Command("heartbeat").description("Run heartbeat daemon \u2014 reports telemetry to the BadgerClaw dashboard every 30s").action(async()=>{let e=b();e||(console.log(g.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=be();console.log(g.default.green(`Heartbeat daemon started (v${t})`)),console.log(g.default.dim(` Instance: ${Z()}`)),console.log(g.default.dim(` Interval: ${dr/1e3}s`)),console.log(g.default.dim(` Press Ctrl+C to stop.
79
+ `));let o=null,n=10,r=0,s=async()=>{try{await yr();let l=await lt(),i=hr(l,t);Ja(o,l)&&o!==null&&console.log(g.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let p=L(),P=await p.post(fr,i);r=0;let O=l.bots.length,f=l.bots.filter(_=>_.status==="running").length;console.log(g.default.dim(` [${new Date().toISOString()}] gateway=${l.status} bots=${f}/${O} running mem=${i.mem_free_mb}MB free`)),o=l;try{let w=await Gn({api:{post:async(X,Ke)=>{let ht=await p.post(X,Ke);return{status:ht.status,data:ht.data}}}});for(let X of w)X.attempted&&(X.posted||X.envUpdated)&&console.log(g.default.cyan(` [${new Date().toISOString()}] Hermes recovery key captured for ${X.bot_id} (posted=${X.posted}, env_updated=${X.envUpdated})`))}catch(_){console.log(g.default.dim(` [${new Date().toISOString()}] Hermes recovery-key retry skipped: ${_.message}`))}let v=P.data?.pending_commands||[],I=!1;for(let _ of v)try{if(console.log(g.default.cyan(` [${new Date().toISOString()}] Received command: ${_.command_type} (${_.id})`)),await p.post(`/api/v1/dashboard/commands/${_.id}/ack`),Vt(_.command_type,_.payload?.bot_id)){console.log(g.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${_.command_type}`));continue}let w=await se(_);console.log(w.success?g.default.green(` [${new Date().toISOString()}] ${w.message}`):g.default.red(` [${new Date().toISOString()}] ${w.message}`)),await p.post(`/api/v1/dashboard/commands/${_.id}/result`,{status:w.success?"success":"failed",result:w.message,new_version:w.newVersion||null}),_.command_type==="update_cli"&&w.success&&(I=!0)}catch(w){console.log(g.default.dim(` [${new Date().toISOString()}] Command ${_.id} error: ${w.message}`))}if(I){console.log(g.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await T()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(l){l instanceof Ae&&(console.log(g.default.yellow(` [${new Date().toISOString()}] Account deactivated \u2014 signed out. Exiting daemon.`)),process.exit(0)),r+=1,console.log(g.default.dim(` [${new Date().toISOString()}] Heartbeat failed (${r}/${n}): ${l.message}`)),r>=n&&(console.log(g.default.red(` [${new Date().toISOString()}] ${n} consecutive heartbeat failures \u2014 exiting so launchctl/systemd can restart the daemon.`)),process.exit(1))}};await s();let a=G()!==null;a?await mr():console.log(g.default.dim(` [${C()}] Hermes-only host \u2014 share-sync disabled (no plugin to push to).`)),setInterval(s,dr),a&&setInterval(mr,Wa),Qa(e.access_token,t);let c=l=>{console.log(g.default.yellow(`
80
+ [${new Date().toISOString()}] Received ${l} \u2014 posting disconnect and exiting.`)),za().finally(()=>{process.exit(0)})};process.on("SIGTERM",c),process.on("SIGINT",c),await new Promise(()=>{})});Xa=2700*1e3});var fs=require("commander");var wr=require("commander"),q=u(require("chalk")),br=u(require("ora")),_r=u(require("open")),Xo=u(require("os"));var oo=u(require("crypto"));function cn(){return oo.default.randomBytes(32).toString("base64url")}function dn(e){return oo.default.createHash("sha256").update(e).digest("base64url")}M();xe();he();oe();rt();var Nt=u(require("os")),J=u(require("fs")),Tt=u(require("path")),ve=require("child_process");var Oe=u(require("fs")),ke=u(require("path")),Ne=u(require("os")),Te=require("child_process"),Yn="ai.badgerclaw.watch",Jn=ke.default.join(Ne.default.homedir(),"Library","LaunchAgents"),Le=ke.default.join(Jn,`${Yn}.plist`);function ea(){try{return(0,Te.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function ta(){try{return(0,Te.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function oa(e){let t=ke.default.join(Ne.default.homedir(),".badgerclaw"),o=ta(),n=ke.default.dirname(o),r=ke.default.dirname(e),s=[n,r,"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"],a=new Set,c=s.filter(l=>!l||a.has(l)?!1:(a.add(l),!0)).join(":");return`<?xml version="1.0" encoding="UTF-8"?>
80
81
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
81
82
  <plist version="1.0">
82
83
  <dict>
83
84
  <key>Label</key>
84
- <string>${Gn}</string>
85
+ <string>${Yn}</string>
85
86
  <key>ProgramArguments</key>
86
87
  <array>
87
88
  <string>${o}</string>
@@ -104,7 +105,7 @@ Keep responses concise and helpful.
104
105
  <key>ThrottleInterval</key>
105
106
  <integer>30</integer>
106
107
  </dict>
107
- </plist>`}function qn(){if(Oe.default.platform()==="darwin")try{let e=Gs();Pe.default.mkdirSync(Wn,{recursive:!0}),Pe.default.mkdirSync(Se.default.join(Oe.default.homedir(),".badgerclaw"),{recursive:!0}),Pe.default.writeFileSync(De,qs(e));try{(0,Ne.execSync)(`launchctl unload "${De}" 2>/dev/null`)}catch{}(0,Ne.execSync)(`launchctl load "${De}"`),console.log("\x1B[2mPair-watcher registered as background service (auto-starts on login).\x1B[0m")}catch{console.log("\x1B[2mNote: could not register background service. Run `badgerclaw watch` manually.\x1B[0m")}}function Vn(){if(Oe.default.platform()==="darwin")try{(0,Ne.execSync)(`launchctl unload "${De}" 2>/dev/null`),Pe.default.existsSync(De)&&Pe.default.unlinkSync(De)}catch{}}var Te=d(require("fs")),rt=d(require("path")),nt=d(require("os")),K=require("child_process"),Ot="badgerclaw-watch.service",Kn=rt.default.join(nt.default.homedir(),".config","systemd","user"),$o=rt.default.join(Kn,Ot);function Vs(){try{return(0,K.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function Ks(){try{return(0,K.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function Js(e){let t=Ks(),o=rt.default.dirname(t);return`[Unit]
108
+ </plist>`}function zn(){if(Ne.default.platform()==="darwin")try{let e=ea();Oe.default.mkdirSync(Jn,{recursive:!0}),Oe.default.mkdirSync(ke.default.join(Ne.default.homedir(),".badgerclaw"),{recursive:!0}),Oe.default.writeFileSync(Le,oa(e));try{(0,Te.execSync)(`launchctl unload "${Le}" 2>/dev/null`)}catch{}(0,Te.execSync)(`launchctl load "${Le}"`),console.log("\x1B[2mPair-watcher registered as background service (auto-starts on login).\x1B[0m")}catch{console.log("\x1B[2mNote: could not register background service. Run `badgerclaw watch` manually.\x1B[0m")}}function Xn(){if(Ne.default.platform()==="darwin")try{(0,Te.execSync)(`launchctl unload "${Le}" 2>/dev/null`),Oe.default.existsSync(Le)&&Oe.default.unlinkSync(Le)}catch{}}var Me=u(require("fs")),at=u(require("path")),st=u(require("os")),Y=require("child_process"),Lt="badgerclaw-watch.service",Qn=at.default.join(st.default.homedir(),".config","systemd","user"),Ro=at.default.join(Qn,Lt);function na(){try{return(0,Y.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function ra(){try{return(0,Y.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function sa(e){let t=ra(),o=at.default.dirname(t);return`[Unit]
108
109
  Description=BadgerClaw background watcher (heartbeat + pair events)
109
110
  After=network-online.target
110
111
  Wants=network-online.target
@@ -120,43 +121,49 @@ StandardError=append:%h/.badgerclaw/heartbeat.log
120
121
 
121
122
  [Install]
122
123
  WantedBy=default.target
123
- `}function Jn(){try{return(0,K.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function Yn(){if(nt.default.platform()!=="linux"||!Jn())return!1;try{let e=Vs();Te.default.mkdirSync(Kn,{recursive:!0}),Te.default.mkdirSync(rt.default.join(nt.default.homedir(),".badgerclaw"),{recursive:!0}),Te.default.writeFileSync($o,Js(e)),(0,K.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,K.execSync)(`systemctl --user restart ${Ot}`,{stdio:"ignore"})}catch{}(0,K.execSync)(`systemctl --user enable --now ${Ot}`,{stdio:"ignore"});try{let t=(0,K.execSync)("whoami",{encoding:"utf-8"}).trim();(0,K.execSync)(`loginctl enable-linger ${t}`,{stdio:"ignore"})}catch{}return console.log("\x1B[2mHeartbeat daemon registered as systemd user service (auto-starts on login).\x1B[0m"),!0}catch{return!1}}function zn(){if(nt.default.platform()==="linux"&&Jn()){try{(0,K.execSync)(`systemctl --user disable --now ${Ot}`,{stdio:"ignore"})}catch{}try{Te.default.existsSync($o)&&Te.default.unlinkSync($o),(0,K.execSync)("systemctl --user daemon-reload",{stdio:"ignore"})}catch{}}}var Co=Tt.default.join(Nt.default.homedir(),".badgerclaw"),st=Tt.default.join(Co,"heartbeat.pid"),Ys=Tt.default.join(Co,"heartbeat.log");function zs(e){if(!e||e.length===0)return!1;let t=s=>/(^|[\\/])node(\.exe)?$/i.test(s||""),o=t(e[0])||t(e[1]),n=e.includes("heartbeat"),r=e.some(s=>/(^|[\\/])badgerclaw($|[\\/. ])/i.test(s)||/[\\/]dist[\\/]index\.js$/.test(s));return o&&n&&r}function Xs(e){try{if(process.platform==="linux")return J.default.readFileSync(`/proc/${e}/cmdline`).toString("utf-8").split("\0").filter(Boolean);let t=(0,ke.execSync)(`ps -o args= -p ${e}`,{encoding:"utf-8"}).trim();return t.length?t.split(/\s+/).filter(Boolean):null}catch{return null}}function Io(e){if(!Number.isFinite(e)||e<=0||e===process.pid||e===process.ppid)return!1;let t=Xs(e);return t?zs(t):!1}function xo(){let e="";try{e=(0,ke.execSync)("pgrep -f heartbeat",{encoding:"utf-8"})}catch{return[]}return e.split(/\s+/).map(t=>parseInt(t,10)).filter(t=>Number.isFinite(t)&&t>0).filter(t=>Io(t))}function Qs(e){try{Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,Math.max(0,e))}catch{}}function Zs(e){try{if(process.platform==="linux"){let r=J.default.readFileSync(`/proc/${e}/status`,"utf-8").match(/^PPid:\s*(\d+)/m),s=r?parseInt(r[1],10):NaN;if(!Number.isFinite(s))return null;let a="";try{a=J.default.readFileSync(`/proc/${s}/comm`,"utf-8").trim()}catch{}return{ppid:s,comm:a}}let t=parseInt((0,ke.execSync)(`ps -o ppid= -p ${e}`,{encoding:"utf-8"}).trim(),10);if(!Number.isFinite(t))return null;let o="";try{o=(0,ke.execSync)(`ps -o comm= -p ${t}`,{encoding:"utf-8"}).trim()}catch{}return{ppid:t,comm:o}}catch{return null}}var ea=/(systemd|supervisord|launchd|runsv|runit|s6-supervise|openrc)/i;function ta(){for(let e of xo()){let t=Zs(e);if(t&&ea.test(t.comm))return e}return null}function oa(){try{let e=parseInt(J.default.readFileSync(st,"utf-8").trim(),10);if(Number.isFinite(e)&&e>0&&Io(e))return!0}catch{}return Qn(),xo().length>0}function Qn(){try{let e=parseInt(J.default.readFileSync(st,"utf-8").trim(),10);if(Number.isFinite(e)&&e>0&&Io(e))return}catch{}try{J.default.rmSync(st,{force:!0})}catch{}}function na(e="SIGTERM"){let t=xo(),o=0;for(let a of t)try{process.kill(a,e),o++}catch{}if(o===0)return 0;let n=a=>{try{return process.kill(a,0),!0}catch{return!1}},r=Date.now()+4e3,s=t.filter(n);for(;s.length>0&&Date.now()<r;)Qs(120),s=s.filter(n);for(let a of s)try{process.kill(a,"SIGKILL")}catch{}return o}function Xn(){if(oa())return console.log("\x1B[2mHeartbeat already running.\x1B[0m"),!0;try{J.default.mkdirSync(Co,{recursive:!0});let e=J.default.openSync(Ys,"a"),t=(0,ke.spawn)(process.execPath,[process.argv[1],"heartbeat"],{detached:!0,stdio:["ignore",e,e]});if(t.pid==null)return console.log("\x1B[2mNote: could not start the heartbeat. Run `badgerclaw heartbeat` manually.\x1B[0m"),!1;try{J.default.writeFileSync(st,String(t.pid))}catch{}return t.unref(),console.log("\x1B[2mHeartbeat started in the background (no service manager on this host; it will not auto-restart after a reboot \u2014 re-run `badgerclaw setup --hermes` or `badgerclaw heartbeat` if the host restarts).\x1B[0m"),!0}catch{return console.log("\x1B[2mNote: could not start the heartbeat. Run `badgerclaw heartbeat` manually.\x1B[0m"),!1}}function Ro(){let e=Nt.default.platform();if(e==="darwin"){qn();return}if(e==="linux"){if(Yn())return;Xn();return}Xn()}function ra(){let e=Nt.default.platform();e==="darwin"?Vn():e==="linux"&&zn(),na();try{J.default.rmSync(st,{force:!0})}catch{}}function Zn(e){let t=e.log||(()=>{}),o=ta();if(o!==null){Qn(),t(`heartbeat already supervised (pid ${o}) \u2014 left in place; cleared any stale pid file.`);return}ra(),t("removed stale heartbeat hooks from previous installs."),e.loggedIn?(Ro(),t("reinstalled a fresh heartbeat daemon for this host.")):t("run `badgerclaw login` to start the heartbeat for this host.")}var me=d(require("fs")),Do=d(require("os")),Bt=d(require("path")),ee=require("child_process"),U=d(require("chalk"));Xe();ue();var tr=Bt.default.join(Do.default.homedir(),".openclaw","openclaw.json");function ca(){return process.platform!=="linux"?!1:!!(me.default.existsSync("/.dockerenv")||(0,ee.spawnSync)("which",["systemctl"],{encoding:"utf-8"}).status!==0)}function or(e=!1){let t=null;try{me.default.existsSync(tr)&&(t=JSON.parse(me.default.readFileSync(tr,"utf-8"))?.gateway?.mode??null)}catch{}if(typeof t=="string"&&t.length>0)return!0;e||console.log(U.default.dim(" Setting gateway.mode=local..."));try{return we(()=>((0,ee.execSync)("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),!0))}catch(o){return e||(console.log(U.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${o.message}`)),console.log(U.default.yellow(" Run `openclaw config set gateway.mode local` manually."))),!1}}async function jt(e={}){let t=e.verbose!==!1,o=c=>{t&&console.log(c)};if(ca())return da(t);o(U.default.dim(" Installing OpenClaw gateway service (if not present)...")),(0,ee.spawnSync)("openclaw",["gateway","install"],{stdio:t?"inherit":"pipe",shell:!0}).status!==0&&o(U.default.yellow(" \u26A0\uFE0F `openclaw gateway install` returned non-zero \u2014 continuing.")),or(!t),o(U.default.dim(" Starting OpenClaw gateway..."));let r=(0,ee.spawnSync)("openclaw",["gateway","start"],{stdio:t?"inherit":"pipe",shell:!0}),s="started";if(r.status!==0&&(r=(0,ee.spawnSync)("openclaw",["gateway","restart"],{stdio:t?"inherit":"pipe",shell:!0}),s="restarted"),r.status!==0)return{ok:!1,error:"gateway start/restart returned non-zero exit"};o(U.default.dim(" Waiting for the gateway to start answering..."));let a=await la(2e4);return a||o(U.default.yellow(" \u26A0\uFE0F Gateway start issued but it is not answering yet \u2014 it may still be booting.")),{ok:!0,state:s,ready:a}}async function la(e,t=Eo,o=500){let n=Date.now()+e;for(;;){if(await t())return!0;if(Date.now()>=n)return!1;await new Promise(r=>setTimeout(r,o))}}async function da(e){let t=l=>{e&&console.log(l)};t(U.default.dim(" Container mode (no systemd) \u2014 running gateway in foreground via nohup.")),or(!e);let o=Bt.default.join(Do.default.homedir(),".openclaw","logs");try{me.default.mkdirSync(o,{recursive:!0})}catch{}let n=Bt.default.join(o,"gateway-foreground.log"),r,s;try{r=me.default.openSync(n,"a"),s=me.default.openSync(n,"a")}catch(l){return{ok:!1,error:`cannot open gateway log at ${n}: ${l.message}`}}let a=(0,ee.spawn)("openclaw",["gateway"],{detached:!0,stdio:["ignore",r,s]});if(a.pid==null)return{ok:!1,error:"failed to spawn `openclaw gateway`"};a.unref(),t(U.default.dim(` Gateway PID: ${a.pid}, log: ${n}`));let c=Date.now()+2e4,i=!1;for(;Date.now()<c;){try{let l=me.default.readFileSync(n,"utf-8");if(l.includes("[gateway] ready")){i=!0;break}if(/EADDRINUSE|FATAL|Error:|gateway start blocked/.test(l))return{ok:!1,error:`gateway aborted on startup \u2014 see ${n}`}}catch{}await new Promise(l=>setTimeout(l,200))}return i?{ok:!0,state:"started",ready:!0}:{ok:!1,error:`gateway did not report ready within 20s \u2014 see ${n}`}}function Mt(){if(process.platform!=="linux"||process.getuid?.()!==0)return;let e=(0,ee.spawnSync)("loginctl",["show-user","root","--property=Linger"],{encoding:"utf-8"});e.status===0&&/Linger=no/.test(e.stdout||"")&&(console.log(U.default.yellow(`
124
- \u26A0\uFE0F systemd lingering is OFF for root. The gateway will stop on SSH disconnect.`)),console.log(U.default.dim(" Enable persistence: loginctl enable-linger root")))}Ae();var Ga=2e3,Wa=12e4,hr=new pr.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=rn(),t=sn(e),o=`${un}/cli-auth?code=${t}`;console.log(q.default.yellow("Opening browser for authentication...")),console.log(q.default.dim(`If the browser doesn't open, visit: ${o}`)),await(0,fr.default)(o);let n=(0,gr.default)("Waiting for authentication...").start(),r=hn(),s=Date.now();for(;Date.now()-s<Wa;){try{let a=await r.post(`/api/v1/openclaw/cli/auth/poll/${t}`,{code_verifier:e,code_challenge:t});if(a.status===429){await new Promise(c=>setTimeout(c,5e3));continue}if(a.data?.access_token){let{access_token:c,user_id:i,expires_at:l,refresh_token:m,email:p}=a.data,E=ro(),D=`openclaw-${Jo.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${E}`,f=D;try{let{version:b}=be(),w=await r.post("/api/v1/openclaw/register",{instance_id:D,label:Jo.default.hostname(),version:b,machine_fingerprint:E},{headers:{Authorization:`Bearer ${c}`}}),x=w.data?.result||w.data;x&&typeof x.instance_id=="string"&&x.instance_id.length>0&&(f=x.instance_id)}catch(b){let w=b?.response?.status;if(w===403||w===409){let x=b?.response?.data,z=Array.isArray(x?.errors)&&typeof x.errors[0]=="string"?x.errors[0]:null,qe=x?.detail,gt=typeof qe=="string"?qe:qe?.error==="downgrade_selection_required"?"Your account has an unresolved plan-change request. Open the BadgerClaw app to finish the downgrade selection, then try again.":null,ss=z||gt||`Login refused (status ${w}). Open the BadgerClaw app to check your subscription state.`;n.fail(q.default.red(ss)),process.exit(1)}}if(ht({access_token:c,user_id:i,instance_id:f,expires_at:l,refresh_token:m,email:p}),n.succeed(q.default.green(`Logged in as ${wt(i)}`)),G()!==null){let b=await jt({verbose:!0});b.ok?b.ready===!1&&console.log(q.default.dim(" Gateway is still coming up \u2014 it should be online shortly.")):console.log(q.default.yellow("\n \u26A0\uFE0F Logged in, but gateway failed to start. Re-run `badgerclaw setup` to repair."))}else console.log(q.default.dim(" Hermes-only host \u2014 skipping OpenClaw gateway bring-up."));let v=await tt(!0);v>0&&console.log(q.default.green(`\u2705 ${v} bot(s) automatically paired to OpenClaw.`)),Ro(),Mt();try{let{pushHeartbeat:b}=await Promise.resolve().then(()=>(Be(),Ko));await b(),console.log(q.default.dim(" Capabilities pushed \u2014 the machine should show online shortly."))}catch(b){console.log(q.default.dim(` Capability push will retry via the heartbeat (${b?.message||b}).`))}return}}catch{}await new Promise(a=>setTimeout(a,Ga))}n.fail(q.default.red("Authentication timed out. Please try again.")),process.exit(1)});var wr=require("commander"),ct=d(require("chalk")),Vt=d(require("fs")),je=d(require("os")),dt=d(require("path")),lt=require("child_process");L();he();function qa(){let e=process.platform;if(e==="darwin"){let t=dt.default.join(je.default.homedir(),"Library","LaunchAgents","ai.badgerclaw.watch.plist");(0,lt.spawnSync)("launchctl",["unload",t],{stdio:"ignore"});try{Vt.default.unlinkSync(t)}catch{}}else if(e==="linux"){(0,lt.spawnSync)("systemctl",["--user","disable","--now","badgerclaw-watch.service"],{stdio:"ignore"});let t=dt.default.join(je.default.homedir(),".config","systemd","user","badgerclaw-watch.service");try{Vt.default.unlinkSync(t)}catch{}(0,lt.spawnSync)("systemctl",["--user","daemon-reload"],{stdio:"ignore"})}(0,lt.spawnSync)("pkill",["-f","badgerclaw heartbeat"],{stdio:"ignore"})}function yr(e){try{return Vt.default.rmSync(e,{recursive:!0,force:!0}),!0}catch{return!1}}var br=new wr.Command("logout").description("Disconnect this machine, log out of BadgerClaw, and wipe local state").option("--keep-state","Only clear auth.json (legacy behaviour); preserve bot-mapping, claude-sessions, heartbeat logs, and plugin quarantine ledger").action(async e=>{let t=_();if(t)try{let a=ze(t.access_token),{version:c}=be();await a.post("/api/v1/openclaw/register",{instance_id:t.instance_id,label:je.default.hostname(),version:c,online:!1})}catch{}if(qa(),e.keepState){Ke(),console.log(ct.default.green("Logged out \u2014 auth cleared. (state preserved with --keep-state)"));return}let o=dt.default.join(je.default.homedir(),".badgerclaw"),n=yr(o),r=dt.default.join(je.default.homedir(),".openclaw","badgerclaw"),s=yr(r);n||s?(console.log(ct.default.green("Logged out \u2014 local state cleared.")),console.log(ct.default.dim(` Removed: ${o}${s?`, ${r}`:""}`))):console.log(ct.default.green("Logged out."))});var _r=require("commander"),Yo=d(require("chalk"));L();var Sr=new _r.Command("status").description("Show connected instance info").action(async()=>{let e=_();(!e||!yt())&&(console.log(Yo.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(Yo.default.green("Authenticated")),console.log(` User: ${wt(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var He=require("commander"),S=d(require("chalk")),zt=d(require("ora")),Yt=d(require("fs")),xr=d(require("os")),Rr=d(require("path")),Ar=require("child_process");L();he();var Me=d(require("fs")),kr=d(require("os")),vr=d(require("path")),$r=require("child_process");Xe();function Kt(e){let t=e.split(":")[0].replace(/^@/,"").replace(/_bot$/,""),o=vr.join(kr.homedir(),".openclaw","openclaw.json");return Me.existsSync(o)?{changed:we(()=>{let r=JSON.parse(Me.readFileSync(o,"utf-8")),s=!1;if(r.channels?.badgerclaw?.accounts?.[t]&&(delete r.channels.badgerclaw.accounts[t],s=!0),r.agents?.list){let a=r.agents.list.length;r.agents.list=r.agents.list.filter(c=>c.id!==t),r.agents.list.length!==a&&(s=!0)}return s&&Me.writeFileSync(o,JSON.stringify(r,null,2)),s})}:{changed:!1}}function Jt(){try{return(0,$r.execSync)("openclaw gateway restart",{stdio:"ignore"}),!0}catch{return!1}}_e();function Cr(e){return e.hermes?"hermes":"openclaw"}function Ir(e){return e.openclaw.installed?"openclaw":e.hermes.installed?"hermes":"openclaw"}function Xo(){yt()||(console.log(S.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function Va(e){return/^[a-z0-9_]{4,20}$/.test(e)}function Er(e){return e.replace(/_bot$/,"")}var zo=["openclaw","hermes"],Ka=new He.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").option("-r, --runtime <runtime>",`Bot runtime: ${zo.join(" | ")}. Default is selected from this host's capabilities (Hermes preferred when available, OpenClaw otherwise \u2014 see \`badgerclaw setup\` output). Hermes requires HERMES_RUNTIME_ENABLED on the backend and a host that advertises Hermes capability via badgerclaw setup. Operator-side LLM credentials (BADGERCLAW_LLM_API_KEY or GOOGLE_API_KEY etc.) must be set at pair time, not at create time.`).action(async(e,t)=>{Xo(),Va(e)||(console.log(S.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let o=t.runtime??Ir(le());zo.includes(o)||(console.log(S.default.red(`Invalid --runtime "${t.runtime}". Must be one of: ${zo.join(", ")}.`)),process.exit(1));let n=(0,zt.default)(`Creating ${o} bot "${e}"...`).start();try{let r=O();o==="hermes"?await r.post("/api/v1/bots",{bot_name:e,bot_username:e,runtime:"hermes"}):await r.post("/api/v1/openclaw/bots",{username:e}),n.succeed(S.default.green(`Bot "${e}" (${o}) created successfully!`)),o==="hermes"&&console.log(S.default.dim(" Next: generate a pair code from Adminweb (or POST /api/v1/pairing/create),\n then run `badgerclaw autopair` on a Hermes-capable host."))}catch(r){let s=r.response?.data?.errors?.[0]||r.message;n.fail(S.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),Ja=new He.Command("list").description("List your bots").action(async()=>{Xo();let e=(0,zt.default)("Fetching bots...").start();try{let n=(await O().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),n.length===0){console.log(S.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(S.default.green(`Your bots (${n.length}):
125
- `));for(let r of n){let s=Er(r.username||r.name),a=r.active===!1?S.default.dim("deactivated"):r.openclaw_connected?S.default.green("connected"):S.default.gray("disconnected");console.log(` ${S.default.bold(s)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(S.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),Ya=new He.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{Xo();let t=(0,zt.default)(`Deactivating bot "${e}"...`).start();try{await O().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(S.default.green(`Bot "${e}" deactivated.`));let{changed:n}=Kt(e);n&&(console.log(S.default.dim(" Removed from openclaw.json")),Jt()&&console.log(S.default.dim(" Gateway restarted")))}catch(o){let n=o.response?.data?.errors?.[0]||o.message;t.fail(S.default.red(`Failed to deactivate bot: ${n}`)),process.exit(1)}});function za(e){let t=e.trim();return t.startsWith("@")&&(t=t.slice(1)),t.includes(":")&&(t=t.split(":")[0]),Er(t)}function Xa(e){let t=e.replace(/[^a-zA-Z0-9_.-]/g,"_")||"default";return Rr.default.join(xr.default.homedir(),".openclaw","badgerclaw","quarantine",`${t}.json`)}var Qa=new He.Command("refresh").description("Recover a bot stuck in quarantine \u2014 clears the quarantine ledger and restarts the gateway so the plugin's refresh chain runs from scratch").argument("<name>",'Bot name (e.g. "claude", "claude_bot", or full Matrix ID)').action(async e=>{let t=za(e);t||(console.log(S.default.red(`Couldn't parse bot name "${e}".`)),process.exit(1));let o=Xa(t),n=!1;if(Yt.default.existsSync(o))try{let r=JSON.parse(Yt.default.readFileSync(o,"utf-8")),s=r.failureCount??"?",a=r.quarantinedAt??"?";console.log(S.default.dim(` Quarantine for "${t}" \u2014 ${s} failures, since ${a}`)),Yt.default.unlinkSync(o),n=!0}catch(r){console.log(S.default.red(`Failed to clear quarantine ledger at ${o}: ${r.message}`)),process.exit(1)}console.log(n?S.default.green(`\u2705 Cleared quarantine for "${t}"`):S.default.dim(` No quarantine file for "${t}" \u2014 already healthy or never quarantined.`)),console.log(S.default.dim(" Restarting OpenClaw gateway so the refresh chain runs..."));try{(0,Ar.execSync)("openclaw gateway restart",{stdio:"inherit"})}catch(r){console.log(S.default.yellow(` Gateway restart command failed: ${r.message}`)),console.log(S.default.yellow(" Run `openclaw gateway restart` manually.")),process.exit(1)}console.log(S.default.green(`
126
- \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(S.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(S.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(S.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(S.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),Pr=new He.Command("bot").description("Manage bots").addCommand(Ka).addCommand(Ja).addCommand(Ya).addCommand(Qa);ot();var Or=require("commander"),y=d(require("chalk"));L();ae();ot();ue();Be();qo();he();xe();var Dr=3e3,Za=6e4,ei=2700*1e3,Nr=new Or.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{_()||(console.log(y.default.yellow("Not logged in.")),process.exit(1)),await tt(!1),console.log(y.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=Dr,n=null,r=null,s=()=>{let a=_();a||(console.log(y.default.red(" Auth missing \u2014 run `badgerclaw login` and re-start `badgerclaw watch`.")),process.exit(1));let c=new t(`${H}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${a.access_token}`}});r=c,c.onopen=()=>{o=Dr,console.log(y.default.dim(" SSE connected \u2014 listening for events")),n&&clearTimeout(n),n=setTimeout(()=>{console.log(y.default.dim(" SSE proactive reconnect \u2014 refreshing token before expiry")),c.close(),s()},ei)},c.onerror=()=>{c.close(),n&&(clearTimeout(n),n=null),console.log(y.default.dim(` SSE disconnected \u2014 reconnecting in ${Math.floor(o/1e3)}s...`)),setTimeout(s,o),o=Math.min(o*1.5,Za)},c.onmessage=async i=>{try{let l=JSON.parse(i.data);if(l.type==="pair"){let m=l.target_instance_id;if(m&&m!==Q()){console.log(y.default.dim(`
127
- \u{1F4F1} Pair event for ${l.bot_name} targets ${m} \u2014 not us, skipping`));return}console.log(y.default.cyan(`
128
- \u{1F4F1} Pair event received: ${l.bot_name}`)),await et(l.pair_code,l.bot_name,l.bot_user_id,!1);try{let{execSync:p}=await import("child_process");p("openclaw gateway restart",{stdio:"ignore"}),console.log(y.default.green(" \u2705 Gateway restarted \u2014 bot is live!"))}catch{console.log(y.default.dim(" Gateway restart failed \u2014 run: openclaw gateway restart"))}}else if(l.type==="gateway-restart"){console.log(y.default.cyan(`
129
- \u{1F504} Remote gateway-restart command received`));let m=await Le();m.success?console.log(y.default.green(` \u2705 Gateway restarted: ${m.message}`)):console.log(y.default.red(` \u274C Gateway restart failed: ${m.message}`));try{await T(),console.log(y.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(y.default.dim(" Could not push heartbeat."))}}else if((l.type==="bot.delete"||l.type==="bot.disconnect")&&l.bot_user_id){let m=l.bot_user_id,p=l.type==="bot.delete"?"deleted":"disconnected",E=l.type==="bot.delete"?"\u{1F5D1}\uFE0F ":"\u{1F50C}";console.log(y.default.yellow(`
130
- ${E} Bot ${p}: ${m} \u2014 removing from OpenClaw config...`));try{let{changed:D}=Kt(m);D?(console.log(y.default.green(" \u2705 Removed from openclaw.json")),Jt()?console.log(y.default.green(" \u2705 Gateway restarted")):console.log(y.default.dim(" Gateway restart failed \u2014 restart manually"))):console.log(y.default.dim(" Account not found in openclaw.json \u2014 nothing to remove"))}catch(D){console.log(y.default.red(` Failed to update openclaw.json: ${D}`))}}else if(l.type==="claude_code.start"&&l.bot_id&&l.room_id){console.log(y.default.cyan(`
131
- \u{1F916} Claude Code START received: bot=${l.bot_id} room=${l.room_id}`));try{let m=await re({id:l.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:l.bot_id,room_id:l.room_id,session_id:l.session_id}});if(console.log(m.success?y.default.green(` \u2705 ${m.message}`):y.default.red(` \u274C ${m.message}`)),l.command_id)try{await O().post(`/api/v1/dashboard/commands/${l.command_id}/result`,{status:m.success?"success":"failed",result:m.message})}catch{}try{await T()}catch{}}catch(m){console.log(y.default.red(` Claude Code start error: ${m.message}`))}}else if(l.type==="claude_code.stop"&&l.bot_id&&l.room_id){console.log(y.default.cyan(`
132
- \u{1F916} Claude Code STOP received: bot=${l.bot_id} room=${l.room_id}`));try{let m=await re({id:l.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:l.bot_id,room_id:l.room_id,session_id:l.session_id}});if(console.log(m.success?y.default.green(` \u2705 ${m.message}`):y.default.red(` \u274C ${m.message}`)),l.command_id)try{await O().post(`/api/v1/dashboard/commands/${l.command_id}/result`,{status:m.success?"success":"failed",result:m.message})}catch{}try{await T()}catch{}}catch(m){console.log(y.default.red(` Claude Code stop error: ${m.message}`))}}else if(l.type==="command.execute"&&l.command_id){console.log(y.default.cyan(`
133
- \u26A1 SSE command received: ${l.command_type} (${l.command_id})`));try{let m=O();await m.post(`/api/v1/dashboard/commands/${l.command_id}/ack`);let p=await re({id:l.command_id,command_type:l.command_type,payload:l.payload});console.log(p.success?y.default.green(` \u2705 ${p.message}`):y.default.red(` \u274C ${p.message}`)),await m.post(`/api/v1/dashboard/commands/${l.command_id}/result`,{status:p.success?"success":"failed",result:p.message,new_version:p.newVersion||null});try{await T()}catch{}l.command_type==="update_cli"&&p.success&&(console.log(y.default.cyan(" CLI updated \u2014 restarting in 2s...")),setTimeout(()=>process.exit(0),2e3))}catch(m){console.log(y.default.red(` Command ${l.command_id} error: ${m.message}`))}}}catch{}}};s(),await new Promise(()=>{})});var Yr=require("commander"),u=d(require("chalk")),te=require("child_process"),I=d(require("fs")),pt=d(require("os")),se=d(require("path"));ae();Ae();var ut=d(require("fs")),Ue=d(require("path")),Xt=require("child_process"),ti=["request","request-promise"];function oi(e){let t=e.match(/^(\s*)(?:"([^"]+)"|'([^']+)'|([^:#\s][^:]*?))\s*:/);return t?{indent:t[1].length,key:(t[2]??t[3]??t[4]??"").trim()}:null}function ni(e){let t=e.split(`
134
- `),o=[],n=!1,r=-1,s=!1,a=new Set(ti);for(let c of t){let i=oi(c);if(!n){i&&i.indent===0&&i.key==="overrides"&&(n=!0,r=i.indent),o.push(c);continue}if(i&&i.indent<=r){n=!1,o.push(c);continue}if(i&&i.indent>r&&a.has(i.key)){s=!0;continue}o.push(c)}return s?o.join(`
135
- `):null}function ri(){let e=[],t=(0,Xt.spawnSync)("npm",["root","-g"],{encoding:"utf-8",shell:!0});t.status===0&&t.stdout?.trim()&&e.push(Ue.default.join(t.stdout.trim(),"openclaw","pnpm-workspace.yaml"));let o=(0,Xt.spawnSync)("npm",["prefix","-g"],{encoding:"utf-8",shell:!0});o.status===0&&o.stdout?.trim()&&e.push(Ue.default.join(o.stdout.trim(),"lib","node_modules","openclaw","pnpm-workspace.yaml"));let n=(0,Xt.spawnSync)("which",["openclaw"],{encoding:"utf-8"});if(n.status===0&&n.stdout?.trim()){let r=Ue.default.dirname(Ue.default.dirname(n.stdout.trim()));e.push(Ue.default.join(r,"lib","node_modules","openclaw","pnpm-workspace.yaml"))}for(let r of e)try{if(ut.default.existsSync(r))return r}catch{}return null}function Tr(){let e=ri();if(!e)return null;let t;try{t=ut.default.readFileSync(e,"utf-8")}catch{return null}let o=ni(t);if(o===null)return null;try{ut.default.writeFileSync(e,o)}catch{return null}return{yamlPath:e,original:t}}function Lr(e){if(!e)return!1;try{return ut.default.writeFileSync(e.yamlPath,e.original),!0}catch{return!1}}_e();var Ge=require("child_process"),jr=d(require("fs")),P=d(require("chalk")),F={alreadyUp:!1,install:null,start:null,requiresRoot:!1,networkHostRequired:!1,guidance:null},Br='On this distro the bare "docker" package is the podman shim (no dockerd). Install Docker Engine from the official docker-ce repository (https://docs.docker.com/engine/install/), then re-run `badgerclaw setup --hermes`.';function si(e){return e.daemonUp?{...F,alreadyUp:!0}:e.host==="darwin"?e.hasDockerApp?{...F,start:"docker-app"}:e.hasColima?{...F,start:"colima"}:e.binaryPresent?{...F,guidance:"A `docker` CLI is present but no engine we can start (Docker.app / colima) was found and the daemon is not answering. Start your Docker daemon (or `colima start`), then re-run `badgerclaw setup --hermes`."}:e.hasBrew?{...F,install:{tool:"colima",via:"brew"},start:"colima"}:{...F,guidance:"No container engine found and Homebrew is absent. Install Docker Desktop (https://www.docker.com/products/docker-desktop) or Homebrew (https://brew.sh) then colima, and re-run `badgerclaw setup --hermes`."}:e.host==="linux-systemd"?e.binaryPresent?{...F,start:"systemctl",requiresRoot:!0}:e.pkgManager==="apt"?{...F,install:{tool:"docker",via:"apt"},start:"systemctl",requiresRoot:!0}:{...F,guidance:e.pkgManager?Br:"Docker is not installed and no supported package manager (apt) was found. Install Docker, then re-run."}:e.host==="linux-nosystemd"?e.binaryPresent?{...F,start:"dockerd-restricted",requiresRoot:!0,networkHostRequired:!0}:e.pkgManager==="apt"?{...F,install:{tool:"docker",via:"apt"},start:"dockerd-restricted",requiresRoot:!0,networkHostRequired:!0}:{...F,guidance:e.pkgManager?Br:"Docker is not installed and no supported package manager (apt) was found. Install Docker (e.g. `apt-get install -y docker.io`), then re-run."}:{...F,guidance:`Automatic Docker setup isn't supported on this platform (${process.platform}). Install + start Docker manually, then re-run.`}}function Mr(e,t,o=8e3){return(0,Ge.spawnSync)(e,t,{encoding:"utf-8",timeout:o})}function Qo(){let e=Mr("docker",["version","--format","{{.Server.Version}}"],4e3);return e.status===0&&!!(e.stdout||"").trim()}function ai(){return Mr("docker",["--version"],4e3).status===0}function Fe(e){return(0,Ge.spawnSync)("sh",["-c",`command -v ${e}`],{encoding:"utf-8"}).status===0}function ii(){return Fe("apt-get")?"apt":Fe("dnf")?"dnf":Fe("yum")?"yum":null}function ci(){let e=(0,Ge.spawnSync)("systemctl",["is-system-running"],{encoding:"utf-8",timeout:4e3});if(e.error)return!1;let t=`${e.stdout||""}${e.stderr||""}`.toLowerCase();return!/failed to connect to bus|not been booted with systemd|no such file/.test(t)}function li(){return process.platform==="darwin"?"darwin":process.platform==="linux"?ci()?"linux-systemd":"linux-nosystemd":"unsupported"}function di(){return typeof process.getuid=="function"?process.getuid()===0:!1}function pe(e,t){return t(P.default.dim(` $ ${e}`)),(0,Ge.spawnSync)("sh",["-c",e],{stdio:"inherit"}).status===0}function ui(e,t,o){let n=t?"sudo ":"";switch(e.via){case"brew":return o(P.default.dim(" Installing colima + docker CLI via Homebrew...")),pe("brew install colima docker",o);case"apt":return o(P.default.dim(" Installing Docker via apt...")),pe(`${n}apt-get update`,o),pe(`${n}apt-get install -y docker.io`,o);default:return!1}}function mi(e,t,o){let n=t?"sudo ":"";switch(e){case"docker-app":return pe("open -a Docker",o);case"colima":return pe("colima start",o);case"systemctl":return pe(`${n}systemctl enable --now docker`,o);case"dockerd-restricted":{if(!Fe("dockerd"))return o(P.default.red(" \u274C `dockerd` is not installed (the docker CLI alone is not enough on a no-systemd host).")),!1;if(t&&!pe("sudo -v",o))return o(P.default.red(" \u274C root is required to start dockerd here, but sudo is unavailable.")),!1;pe(`${n}sh -c 'mount -t cgroup2 none /sys/fs/cgroup 2>/dev/null || true'`,o);let r="/tmp/badgerclaw-dockerd.log";o(P.default.dim(` Starting dockerd (restricted: --bridge=none --iptables=false) \u2192 ${r}`));let s=`nohup dockerd --storage-driver=overlay2 --iptables=false --bridge=none > ${r} 2>&1 &`,a=t?`sudo sh -c ${JSON.stringify(s)}`:`sh -c ${JSON.stringify(s)}`;return(0,Ge.spawnSync)("sh",["-c",a],{stdio:"ignore"}).status===0}}}async function pi(e,t,o){let n=Date.now()+t;for(;;){if(e())return!0;if(Date.now()>=n)return!1;await new Promise(r=>setTimeout(r,o))}}async function Hr(e={}){let t=e.log??(a=>console.log(a));if(process.env.BADGERCLAW_NO_AUTO_DEPS==="1"){let a=Qo();return a||(t(P.default.yellow(" BADGERCLAW_NO_AUTO_DEPS=1 \u2014 skipping automatic Docker setup.")),t(P.default.dim(" Start the Docker daemon yourself, then re-run `badgerclaw setup --hermes`."))),{ok:a,daemonUp:a,networkHostRequired:!1}}let o={daemonUp:Qo(),binaryPresent:ai(),host:li(),hasBrew:Fe("brew"),hasDockerApp:jr.default.existsSync("/Applications/Docker.app"),hasColima:Fe("colima"),pkgManager:ii(),isRoot:di()},n=si(o);if(n.alreadyUp)return{ok:!0,daemonUp:!0,networkHostRequired:!1};if(n.guidance)return t(P.default.red(` \u274C ${n.guidance}`)),{ok:!1,daemonUp:!1,networkHostRequired:n.networkHostRequired};let r=n.requiresRoot&&!o.isRoot;return r&&t(P.default.dim(" (some steps need root \u2014 using sudo; you may be prompted for your password)")),n.install&&!ui(n.install,r,t)?(t(P.default.red(" \u274C Docker install failed (see output above). Install it manually, then re-run.")),{ok:!1,daemonUp:!1,networkHostRequired:n.networkHostRequired}):mi(n.start,r,t)?(t(P.default.dim(" Waiting for the Docker daemon to answer...")),await pi(Qo,12e4,1500)?(t(P.default.green(" \u2705 Docker daemon is up.")),{ok:!0,daemonUp:!0,networkHostRequired:n.networkHostRequired}):(t(P.default.red(" \u274C Docker did not become ready in time.")),n.start==="dockerd-restricted"?t(P.default.dim(" Check /tmp/badgerclaw-dockerd.log for the daemon output.")):n.start==="docker-app"&&t(P.default.dim(" Docker Desktop can take a minute to boot \u2014 re-run once its menu-bar icon is steady.")),{ok:!1,daemonUp:!1,networkHostRequired:n.networkHostRequired})):(t(P.default.red(" \u274C Could not start Docker (see output above). Resolve it, then re-run.")),{ok:!1,daemonUp:!1,networkHostRequired:n.networkHostRequired})}function Ur(e){let t=e.minMajor??18;if(!Number.isFinite(e.nodeMajor)||e.nodeMajor<t){let o=Number.isFinite(e.nodeMajor)?`Node v${e.nodeMajor}`:"an unknown Node version";return`badgerclaw requires Node.js >= ${t} (this is ${o}). Upgrade Node \u2014 nodesource (https://github.com/nodesource/distributions) or nvm (\`nvm install ${t}\`) \u2014 then re-run \`badgerclaw setup --hermes\`.`}return e.npmPresent?null:`npm was not found on PATH. badgerclaw is installed and updated via npm \u2014 install Node.js ${t}+ (which bundles npm) and re-run \`badgerclaw setup --hermes\`.`}function Fr(e=process.versions.node){return parseInt(String(e).split(".")[0],10)}var Zo=require("child_process"),Qt=d(require("fs")),Gr=d(require("os")),Zt=d(require("path"));_e();Pt();function gi(){let e=Wr();for(let t of e)if(Qt.default.existsSync(t))return t;return null}function Wr(){return[Zt.default.resolve(__dirname,"..","assets","hermes-agent-bc.Dockerfile"),Zt.default.resolve(__dirname,"..","..","assets","hermes-agent-bc.Dockerfile")]}var fi="nousresearch/hermes-agent";function hi(e){let t=(process.env.HERMES_UPSTREAM||e?.upstream||"").trim();if(!t)return;if(t.includes("/"))return t;let o=t.includes(":")?t.split(":").pop():t;return`${fi}:${o}`}var yi={run:e=>{let t=(0,Zo.spawnSync)("docker",e,{encoding:"utf-8"});return{status:t.status,stdout:t.stdout||"",stderr:t.stderr||""}}};function wi(e){return["build",...e.hostNetwork?["--network","host"]:[],...e.upstreamRef?["--build-arg",`UPSTREAM=${e.upstreamRef}`]:[],"-t",e.image,"-f",e.dockerfile,e.ctxDir]}function qr(e){let t=Ct();if(!t.installed)return{status:"no-docker"};let o=process.env.HERMES_IMAGE||Ee;if(It(t).installed)return{status:"already-present",image:o};let r=gi();if(!r)return{status:"no-dockerfile",expectedPaths:Wr()};let s=hi(e),a=wo({bridgeUsable:()=>Et(yi)}),c=Qt.default.mkdtempSync(Zt.default.join(Gr.default.tmpdir(),"bc-hermes-build-"));try{let i=(0,Zo.spawnSync)("docker",wi({hostNetwork:a,upstreamRef:s,image:o,dockerfile:r,ctxDir:c}),{stdio:"inherit",timeout:6e5});return i.status===0?{status:"built",image:o}:{status:"build-failed",image:o,stderr:`docker build exited ${i.status??"<no-status>"}`}}finally{try{Qt.default.rmSync(c,{recursive:!0,force:!0})}catch{}}}L();var Y=se.default.join(pt.default.homedir(),".openclaw","openclaw.json"),mt=Y+".badgerclaw-stash",zr=se.default.join(pt.default.homedir(),".openclaw","npm"),bi=se.default.join(zr,"package.json");async function Vr(){try{let e=await fetch(`${H}/api/v1/dashboard/versions/latest`,{headers:{Accept:"application/json"}});if(!e.ok)return{cli:null,plugin:null,openclaw:null,hermes:null};let t=await e.json(),o=t.result&&typeof t.result=="object"?t.result:t,n=r=>typeof r!="string"||!r||r==="unknown"?null:r;return{cli:n(o.cli),plugin:n(o.plugin),openclaw:n(o.supported_openclaw),hermes:n(o.supported_hermes)}}catch{return{cli:null,plugin:null,openclaw:null,hermes:null}}}function _i(){if(!I.default.existsSync(Y))return null;try{let e=JSON.parse(I.default.readFileSync(Y,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,I.default.writeFileSync(Y,JSON.stringify(e,null,2)),I.default.writeFileSync(mt,JSON.stringify(t,null,2)),t):null}catch{return null}}function Si(){if(!I.default.existsSync(Y))return null;try{let e=JSON.parse(I.default.readFileSync(Y,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function ki(e){if(e&&I.default.existsSync(Y))try{let t=JSON.parse(I.default.readFileSync(Y,"utf-8"));t.gateway={...e,...t.gateway||{}},I.default.writeFileSync(Y,JSON.stringify(t,null,2))}catch(t){console.log(u.default.yellow(` \u26A0\uFE0F Could not restore gateway block: ${t.message}`)),console.log(u.default.yellow(" Run `openclaw config set gateway.mode local` manually if the gateway fails to start."))}}function vi(){if(I.default.existsSync(mt))try{let e=JSON.parse(I.default.readFileSync(mt,"utf-8")),t=JSON.parse(I.default.readFileSync(Y,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,I.default.writeFileSync(Y,JSON.stringify(t,null,2)),I.default.unlinkSync(mt)}catch(e){console.log(u.default.yellow(` \u26A0\uFE0F Could not restore config: ${e.message}`)),console.log(u.default.yellow(` Your bot credentials are backed up at: ${mt}`))}}async function Kr(e){return new Promise(t=>{let o=(0,te.spawn)("openclaw",["plugins","install",e,"--force","--dangerously-force-unsafe-install"],{stdio:["ignore","pipe","pipe"],shell:!0}),n="",r=!1,s=!1,a=/Installed plugin:|Restart the gateway to load plugins/,c=()=>{r||s||(r=!0,setTimeout(()=>{if(!s){try{o.kill("SIGTERM")}catch{}setTimeout(()=>{if(!s)try{o.kill("SIGKILL")}catch{}},1e3)}},3e3))},i=(l,m)=>{m.write(l),n+=l.toString("utf-8"),a.test(n)&&c()};o.stdout.on("data",l=>i(l,process.stdout)),o.stderr.on("data",l=>i(l,process.stderr)),o.on("exit",l=>{s=!0,t({status:r?0:l??1})}),o.on("error",l=>{s||(s=!0,console.error(u.default.red(` openclaw spawn error: ${l.message}`)),t({status:1}))})})}function Jr(e){if(!I.default.existsSync(e))return!1;let t;try{t=JSON.parse(I.default.readFileSync(e,"utf-8"))}catch{return!1}let o=!1;return t.overrides&&typeof t.overrides=="object"&&"uuid"in t.overrides&&(delete t.overrides.uuid,o=!0),t.openclaw&&Array.isArray(t.openclaw.managedOverrides)&&t.openclaw.managedOverrides.includes("uuid")&&(t.openclaw.managedOverrides=t.openclaw.managedOverrides.filter(n=>n!=="uuid"),o=!0),o?(I.default.writeFileSync(e,JSON.stringify(t,null,2)+`
136
- `),!0):!1}function $i(){let e=[];Jr(bi)&&e.push(zr);for(let t of vt())Jr(se.default.join(t,"package.json"))&&e.push(t);return e}async function Ci(){let{detectCapabilities:e}=await Promise.resolve().then(()=>(_e(),En)),{pushHeartbeat:t}=await Promise.resolve().then(()=>(Be(),Ko));console.log(u.default.green(`
124
+ `}function Zn(){try{return(0,Y.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function er(){if(st.default.platform()!=="linux"||!Zn())return!1;try{let e=na();Me.default.mkdirSync(Qn,{recursive:!0}),Me.default.mkdirSync(at.default.join(st.default.homedir(),".badgerclaw"),{recursive:!0}),Me.default.writeFileSync(Ro,sa(e)),(0,Y.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,Y.execSync)(`systemctl --user restart ${Lt}`,{stdio:"ignore"})}catch{}(0,Y.execSync)(`systemctl --user enable --now ${Lt}`,{stdio:"ignore"});try{let t=(0,Y.execSync)("whoami",{encoding:"utf-8"}).trim();(0,Y.execSync)(`loginctl enable-linger ${t}`,{stdio:"ignore"})}catch{}return console.log("\x1B[2mHeartbeat daemon registered as systemd user service (auto-starts on login).\x1B[0m"),!0}catch{return!1}}function tr(){if(st.default.platform()==="linux"&&Zn()){try{(0,Y.execSync)(`systemctl --user disable --now ${Lt}`,{stdio:"ignore"})}catch{}try{Me.default.existsSync(Ro)&&Me.default.unlinkSync(Ro),(0,Y.execSync)("systemctl --user daemon-reload",{stdio:"ignore"})}catch{}}}var xo=Tt.default.join(Nt.default.homedir(),".badgerclaw"),it=Tt.default.join(xo,"heartbeat.pid"),aa=Tt.default.join(xo,"heartbeat.log");function ia(e){if(!e||e.length===0)return!1;let t=s=>/(^|[\\/])node(\.exe)?$/i.test(s||""),o=t(e[0])||t(e[1]),n=e.includes("heartbeat"),r=e.some(s=>/(^|[\\/])badgerclaw($|[\\/. ])/i.test(s)||/[\\/]dist[\\/]index\.js$/.test(s));return o&&n&&r}function la(e){try{if(process.platform==="linux")return J.default.readFileSync(`/proc/${e}/cmdline`).toString("utf-8").split("\0").filter(Boolean);let t=(0,ve.execSync)(`ps -o args= -p ${e}`,{encoding:"utf-8"}).trim();return t.length?t.split(/\s+/).filter(Boolean):null}catch{return null}}function Ao(e){if(!Number.isFinite(e)||e<=0||e===process.pid||e===process.ppid)return!1;let t=la(e);return t?ia(t):!1}function Eo(){let e="";try{e=(0,ve.execSync)("pgrep -f heartbeat",{encoding:"utf-8"})}catch{return[]}return e.split(/\s+/).map(t=>parseInt(t,10)).filter(t=>Number.isFinite(t)&&t>0).filter(t=>Ao(t))}function ca(e){try{Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,Math.max(0,e))}catch{}}function da(e){try{if(process.platform==="linux"){let r=J.default.readFileSync(`/proc/${e}/status`,"utf-8").match(/^PPid:\s*(\d+)/m),s=r?parseInt(r[1],10):NaN;if(!Number.isFinite(s))return null;let a="";try{a=J.default.readFileSync(`/proc/${s}/comm`,"utf-8").trim()}catch{}return{ppid:s,comm:a}}let t=parseInt((0,ve.execSync)(`ps -o ppid= -p ${e}`,{encoding:"utf-8"}).trim(),10);if(!Number.isFinite(t))return null;let o="";try{o=(0,ve.execSync)(`ps -o comm= -p ${t}`,{encoding:"utf-8"}).trim()}catch{}return{ppid:t,comm:o}}catch{return null}}var ua=/(systemd|supervisord|launchd|runsv|runit|s6-supervise|openrc)/i;function ma(){for(let e of Eo()){let t=da(e);if(t&&ua.test(t.comm))return e}return null}function pa(){try{let e=parseInt(J.default.readFileSync(it,"utf-8").trim(),10);if(Number.isFinite(e)&&e>0&&Ao(e))return!0}catch{}return nr(),Eo().length>0}function nr(){try{let e=parseInt(J.default.readFileSync(it,"utf-8").trim(),10);if(Number.isFinite(e)&&e>0&&Ao(e))return}catch{}try{J.default.rmSync(it,{force:!0})}catch{}}function ga(e="SIGTERM"){let t=Eo(),o=0;for(let a of t)try{process.kill(a,e),o++}catch{}if(o===0)return 0;let n=a=>{try{return process.kill(a,0),!0}catch{return!1}},r=Date.now()+4e3,s=t.filter(n);for(;s.length>0&&Date.now()<r;)ca(120),s=s.filter(n);for(let a of s)try{process.kill(a,"SIGKILL")}catch{}return o}function or(){if(pa())return console.log("\x1B[2mHeartbeat already running.\x1B[0m"),!0;try{J.default.mkdirSync(xo,{recursive:!0});let e=J.default.openSync(aa,"a"),t=(0,ve.spawn)(process.execPath,[process.argv[1],"heartbeat"],{detached:!0,stdio:["ignore",e,e]});if(t.pid==null)return console.log("\x1B[2mNote: could not start the heartbeat. Run `badgerclaw heartbeat` manually.\x1B[0m"),!1;try{J.default.writeFileSync(it,String(t.pid))}catch{}return t.unref(),console.log("\x1B[2mHeartbeat started in the background (no service manager on this host; it will not auto-restart after a reboot \u2014 re-run `badgerclaw setup --hermes` or `badgerclaw heartbeat` if the host restarts).\x1B[0m"),!0}catch{return console.log("\x1B[2mNote: could not start the heartbeat. Run `badgerclaw heartbeat` manually.\x1B[0m"),!1}}function Po(){let e=Nt.default.platform();if(e==="darwin"){zn();return}if(e==="linux"){if(er())return;or();return}or()}function fa(){let e=Nt.default.platform();e==="darwin"?Xn():e==="linux"&&tr(),ga();try{J.default.rmSync(it,{force:!0})}catch{}}function rr(e){let t=e.log||(()=>{}),o=ma();if(o!==null){nr(),t(`heartbeat already supervised (pid ${o}) \u2014 left in place; cleared any stale pid file.`);return}fa(),t("removed stale heartbeat hooks from previous installs."),e.loggedIn?(Po(),t("reinstalled a fresh heartbeat daemon for this host.")):t("run `badgerclaw login` to start the heartbeat for this host.")}var me=u(require("fs")),No=u(require("os")),Bt=u(require("path")),ee=require("child_process"),U=u(require("chalk"));Ze();ue();var ar=Bt.default.join(No.default.homedir(),".openclaw","openclaw.json");function ba(){return process.platform!=="linux"?!1:!!(me.default.existsSync("/.dockerenv")||(0,ee.spawnSync)("which",["systemctl"],{encoding:"utf-8"}).status!==0)}function ir(e=!1){let t=null;try{me.default.existsSync(ar)&&(t=JSON.parse(me.default.readFileSync(ar,"utf-8"))?.gateway?.mode??null)}catch{}if(typeof t=="string"&&t.length>0)return!0;e||console.log(U.default.dim(" Setting gateway.mode=local..."));try{return we(()=>((0,ee.execSync)("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),!0))}catch(o){return e||(console.log(U.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${o.message}`)),console.log(U.default.yellow(" Run `openclaw config set gateway.mode local` manually."))),!1}}async function jt(e={}){let t=e.verbose!==!1,o=c=>{t&&console.log(c)};if(ba())return Sa(t);o(U.default.dim(" Installing OpenClaw gateway service (if not present)...")),(0,ee.spawnSync)("openclaw",["gateway","install"],{stdio:t?"inherit":"pipe",shell:!0}).status!==0&&o(U.default.yellow(" \u26A0\uFE0F `openclaw gateway install` returned non-zero \u2014 continuing.")),ir(!t),o(U.default.dim(" Starting OpenClaw gateway..."));let r=(0,ee.spawnSync)("openclaw",["gateway","start"],{stdio:t?"inherit":"pipe",shell:!0}),s="started";if(r.status!==0&&(r=(0,ee.spawnSync)("openclaw",["gateway","restart"],{stdio:t?"inherit":"pipe",shell:!0}),s="restarted"),r.status!==0)return{ok:!1,error:"gateway start/restart returned non-zero exit"};o(U.default.dim(" Waiting for the gateway to start answering..."));let a=await _a(2e4);return a||o(U.default.yellow(" \u26A0\uFE0F Gateway start issued but it is not answering yet \u2014 it may still be booting.")),{ok:!0,state:s,ready:a}}async function _a(e,t=Oo,o=500){let n=Date.now()+e;for(;;){if(await t())return!0;if(Date.now()>=n)return!1;await new Promise(r=>setTimeout(r,o))}}async function Sa(e){let t=i=>{e&&console.log(i)};t(U.default.dim(" Container mode (no systemd) \u2014 running gateway in foreground via nohup.")),ir(!e);let o=Bt.default.join(No.default.homedir(),".openclaw","logs");try{me.default.mkdirSync(o,{recursive:!0})}catch{}let n=Bt.default.join(o,"gateway-foreground.log"),r,s;try{r=me.default.openSync(n,"a"),s=me.default.openSync(n,"a")}catch(i){return{ok:!1,error:`cannot open gateway log at ${n}: ${i.message}`}}let a=(0,ee.spawn)("openclaw",["gateway"],{detached:!0,stdio:["ignore",r,s]});if(a.pid==null)return{ok:!1,error:"failed to spawn `openclaw gateway`"};a.unref(),t(U.default.dim(` Gateway PID: ${a.pid}, log: ${n}`));let c=Date.now()+2e4,l=!1;for(;Date.now()<c;){try{let i=me.default.readFileSync(n,"utf-8");if(i.includes("[gateway] ready")){l=!0;break}if(/EADDRINUSE|FATAL|Error:|gateway start blocked/.test(i))return{ok:!1,error:`gateway aborted on startup \u2014 see ${n}`}}catch{}await new Promise(i=>setTimeout(i,200))}return l?{ok:!0,state:"started",ready:!0}:{ok:!1,error:`gateway did not report ready within 20s \u2014 see ${n}`}}function Ht(){if(process.platform!=="linux"||process.getuid?.()!==0)return;let e=(0,ee.spawnSync)("loginctl",["show-user","root","--property=Linger"],{encoding:"utf-8"});e.status===0&&/Linger=no/.test(e.stdout||"")&&(console.log(U.default.yellow(`
125
+ \u26A0\uFE0F systemd lingering is OFF for root. The gateway will stop on SSH disconnect.`)),console.log(U.default.dim(" Enable persistence: loginctl enable-linger root")))}Ee();var ei=2e3,ti=12e4,Sr=new wr.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=cn(),t=dn(e),o=`${fn}/cli-auth?code=${t}`;console.log(q.default.yellow("Opening browser for authentication...")),console.log(q.default.dim(`If the browser doesn't open, visit: ${o}`)),await(0,_r.default)(o);let n=(0,br.default)("Waiting for authentication...").start(),r=_n(),s=Date.now();for(;Date.now()-s<ti;){try{let a=await r.post(`/api/v1/openclaw/cli/auth/poll/${t}`,{code_verifier:e,code_challenge:t});if(a.status===429){await new Promise(c=>setTimeout(c,5e3));continue}if(a.data?.access_token){let{access_token:c,user_id:l,expires_at:i,refresh_token:m,email:p}=a.data,P=so(),O=`openclaw-${Xo.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${P}`,f=O;try{let{version:I}=be(),_=await r.post("/api/v1/openclaw/register",{instance_id:O,label:Xo.default.hostname(),version:I,machine_fingerprint:P},{headers:{Authorization:`Bearer ${c}`}}),w=_.data?.result||_.data;w&&typeof w.instance_id=="string"&&w.instance_id.length>0&&(f=w.instance_id)}catch(I){let _=I?.response?.status;if(_===403||_===409){let w=I?.response?.data,X=Array.isArray(w?.errors)&&typeof w.errors[0]=="string"?w.errors[0]:null,Ke=w?.detail,ht=typeof Ke=="string"?Ke:Ke?.error==="downgrade_selection_required"?"Your account has an unresolved plan-change request. Open the BadgerClaw app to finish the downgrade selection, then try again.":null,hs=X||ht||`Login refused (status ${_}). Open the BadgerClaw app to check your subscription state.`;n.fail(q.default.red(hs)),process.exit(1)}}if(wt({access_token:c,user_id:l,instance_id:f,expires_at:i,refresh_token:m,email:p}),n.succeed(q.default.green(`Logged in as ${_t(l)}`)),G()!==null){let I=await jt({verbose:!0});I.ok?I.ready===!1&&console.log(q.default.dim(" Gateway is still coming up \u2014 it should be online shortly.")):console.log(q.default.yellow("\n \u26A0\uFE0F Logged in, but gateway failed to start. Re-run `badgerclaw setup` to repair."))}else console.log(q.default.dim(" Hermes-only host \u2014 skipping OpenClaw gateway bring-up."));let v=await nt(!0);v>0&&console.log(q.default.green(`\u2705 ${v} bot(s) automatically paired to OpenClaw.`)),Po(),Ht();try{let{pushHeartbeat:I}=await Promise.resolve().then(()=>(je(),zo));await I(),console.log(q.default.dim(" Capabilities pushed \u2014 the machine should show online shortly."))}catch(I){console.log(q.default.dim(` Capability push will retry via the heartbeat (${I?.message||I}).`))}return}}catch{}await new Promise(a=>setTimeout(a,ei))}n.fail(q.default.red("Authentication timed out. Please try again.")),process.exit(1)});var vr=require("commander"),dt=u(require("chalk")),Kt=u(require("fs")),He=u(require("os")),mt=u(require("path")),ut=require("child_process");M();he();function oi(){let e=process.platform;if(e==="darwin"){let t=mt.default.join(He.default.homedir(),"Library","LaunchAgents","ai.badgerclaw.watch.plist");(0,ut.spawnSync)("launchctl",["unload",t],{stdio:"ignore"});try{Kt.default.unlinkSync(t)}catch{}}else if(e==="linux"){(0,ut.spawnSync)("systemctl",["--user","disable","--now","badgerclaw-watch.service"],{stdio:"ignore"});let t=mt.default.join(He.default.homedir(),".config","systemd","user","badgerclaw-watch.service");try{Kt.default.unlinkSync(t)}catch{}(0,ut.spawnSync)("systemctl",["--user","daemon-reload"],{stdio:"ignore"})}(0,ut.spawnSync)("pkill",["-f","badgerclaw heartbeat"],{stdio:"ignore"})}function kr(e){try{return Kt.default.rmSync(e,{recursive:!0,force:!0}),!0}catch{return!1}}var $r=new vr.Command("logout").description("Disconnect this machine, log out of BadgerClaw, and wipe local state").option("--keep-state","Only clear auth.json (legacy behaviour); preserve bot-mapping, claude-sessions, heartbeat logs, and plugin quarantine ledger").action(async e=>{let t=b();if(t)try{let a=Qe(t.access_token),{version:c}=be();await a.post("/api/v1/openclaw/register",{instance_id:t.instance_id,label:He.default.hostname(),version:c,online:!1})}catch{}if(oi(),e.keepState){Je(),console.log(dt.default.green("Logged out \u2014 auth cleared. (state preserved with --keep-state)"));return}let o=mt.default.join(He.default.homedir(),".badgerclaw"),n=kr(o),r=mt.default.join(He.default.homedir(),".openclaw","badgerclaw"),s=kr(r);n||s?(console.log(dt.default.green("Logged out \u2014 local state cleared.")),console.log(dt.default.dim(` Removed: ${o}${s?`, ${r}`:""}`))):console.log(dt.default.green("Logged out."))});var Cr=require("commander"),Qo=u(require("chalk"));M();var Ir=new Cr.Command("status").description("Show connected instance info").action(async()=>{let e=b();(!e||!bt())&&(console.log(Qo.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(Qo.default.green("Authenticated")),console.log(` User: ${_t(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var Fe=require("commander"),S=u(require("chalk")),Xt=u(require("ora")),zt=u(require("fs")),Dr=u(require("os")),Or=u(require("path")),Lr=require("child_process");M();he();var Ue=u(require("fs")),Rr=u(require("os")),xr=u(require("path")),Ar=require("child_process");Ze();function Yt(e){let t=e.split(":")[0].replace(/^@/,"").replace(/_bot$/,""),o=xr.join(Rr.homedir(),".openclaw","openclaw.json");return Ue.existsSync(o)?{changed:we(()=>{let r=JSON.parse(Ue.readFileSync(o,"utf-8")),s=!1;if(r.channels?.badgerclaw?.accounts?.[t]&&(delete r.channels.badgerclaw.accounts[t],s=!0),r.agents?.list){let a=r.agents.list.length;r.agents.list=r.agents.list.filter(c=>c.id!==t),r.agents.list.length!==a&&(s=!0)}return s&&Ue.writeFileSync(o,JSON.stringify(r,null,2)),s})}:{changed:!1}}function Jt(){try{return(0,Ar.execSync)("openclaw gateway restart",{stdio:"ignore"}),!0}catch{return!1}}_e();function Er(e){return e.hermes?"hermes":"openclaw"}function Pr(e){return e.openclaw.installed?"openclaw":e.hermes.installed?"hermes":"openclaw"}function en(){bt()||(console.log(S.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function ni(e){return/^[a-z0-9_]{4,20}$/.test(e)}function Nr(e){return e.replace(/_bot$/,"")}var Zo=["openclaw","hermes"],ri=new Fe.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").option("-r, --runtime <runtime>",`Bot runtime: ${Zo.join(" | ")}. Default is selected from this host's capabilities (Hermes preferred when available, OpenClaw otherwise \u2014 see \`badgerclaw setup\` output). Hermes requires HERMES_RUNTIME_ENABLED on the backend and a host that advertises Hermes capability via badgerclaw setup. Operator-side LLM credentials (BADGERCLAW_LLM_API_KEY or GOOGLE_API_KEY etc.) must be set at pair time, not at create time.`).action(async(e,t)=>{en(),ni(e)||(console.log(S.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let o=t.runtime??Pr(ce());Zo.includes(o)||(console.log(S.default.red(`Invalid --runtime "${t.runtime}". Must be one of: ${Zo.join(", ")}.`)),process.exit(1));let n=(0,Xt.default)(`Creating ${o} bot "${e}"...`).start();try{let r=L();o==="hermes"?await r.post("/api/v1/bots",{bot_name:e,bot_username:e,runtime:"hermes"}):await r.post("/api/v1/openclaw/bots",{username:e}),n.succeed(S.default.green(`Bot "${e}" (${o}) created successfully!`)),o==="hermes"&&console.log(S.default.dim(" Next: generate a pair code from Adminweb (or POST /api/v1/pairing/create),\n then run `badgerclaw autopair` on a Hermes-capable host."))}catch(r){let s=r.response?.data?.errors?.[0]||r.message;n.fail(S.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),si=new Fe.Command("list").description("List your bots").action(async()=>{en();let e=(0,Xt.default)("Fetching bots...").start();try{let n=(await L().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),n.length===0){console.log(S.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(S.default.green(`Your bots (${n.length}):
126
+ `));for(let r of n){let s=Nr(r.username||r.name),a=r.active===!1?S.default.dim("deactivated"):r.openclaw_connected?S.default.green("connected"):S.default.gray("disconnected");console.log(` ${S.default.bold(s)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(S.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),ai=new Fe.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{en();let t=(0,Xt.default)(`Deactivating bot "${e}"...`).start();try{await L().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(S.default.green(`Bot "${e}" deactivated.`));let{changed:n}=Yt(e);n&&(console.log(S.default.dim(" Removed from openclaw.json")),Jt()&&console.log(S.default.dim(" Gateway restarted")))}catch(o){let n=o.response?.data?.errors?.[0]||o.message;t.fail(S.default.red(`Failed to deactivate bot: ${n}`)),process.exit(1)}});function ii(e){let t=e.trim();return t.startsWith("@")&&(t=t.slice(1)),t.includes(":")&&(t=t.split(":")[0]),Nr(t)}function li(e){let t=e.replace(/[^a-zA-Z0-9_.-]/g,"_")||"default";return Or.default.join(Dr.default.homedir(),".openclaw","badgerclaw","quarantine",`${t}.json`)}var ci=new Fe.Command("refresh").description("Recover a bot stuck in quarantine \u2014 clears the quarantine ledger and restarts the gateway so the plugin's refresh chain runs from scratch").argument("<name>",'Bot name (e.g. "claude", "claude_bot", or full Matrix ID)').action(async e=>{let t=ii(e);t||(console.log(S.default.red(`Couldn't parse bot name "${e}".`)),process.exit(1));let o=li(t),n=!1;if(zt.default.existsSync(o))try{let r=JSON.parse(zt.default.readFileSync(o,"utf-8")),s=r.failureCount??"?",a=r.quarantinedAt??"?";console.log(S.default.dim(` Quarantine for "${t}" \u2014 ${s} failures, since ${a}`)),zt.default.unlinkSync(o),n=!0}catch(r){console.log(S.default.red(`Failed to clear quarantine ledger at ${o}: ${r.message}`)),process.exit(1)}console.log(n?S.default.green(`\u2705 Cleared quarantine for "${t}"`):S.default.dim(` No quarantine file for "${t}" \u2014 already healthy or never quarantined.`)),console.log(S.default.dim(" Restarting OpenClaw gateway so the refresh chain runs..."));try{(0,Lr.execSync)("openclaw gateway restart",{stdio:"inherit"})}catch(r){console.log(S.default.yellow(` Gateway restart command failed: ${r.message}`)),console.log(S.default.yellow(" Run `openclaw gateway restart` manually.")),process.exit(1)}console.log(S.default.green(`
127
+ \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(S.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(S.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(S.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(S.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),Tr=new Fe.Command("bot").description("Manage bots").addCommand(ri).addCommand(si).addCommand(ai).addCommand(ci);rt();var Br=require("commander"),y=u(require("chalk"));M();oe();rt();ue();je();Yo();he();xe();var Mr=3e3,di=6e4,ui=2700*1e3,jr=new Br.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{b()||(console.log(y.default.yellow("Not logged in.")),process.exit(1)),await nt(!1),console.log(y.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=Mr,n=null,r=null,s=()=>{let a=b();a||(console.log(y.default.red(" Auth missing \u2014 run `badgerclaw login` and re-start `badgerclaw watch`.")),process.exit(1));let c=new t(`${N}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${a.access_token}`}});r=c,c.onopen=()=>{o=Mr,console.log(y.default.dim(" SSE connected \u2014 listening for events")),n&&clearTimeout(n),n=setTimeout(()=>{console.log(y.default.dim(" SSE proactive reconnect \u2014 refreshing token before expiry")),c.close(),s()},ui)},c.onerror=()=>{c.close(),n&&(clearTimeout(n),n=null),console.log(y.default.dim(` SSE disconnected \u2014 reconnecting in ${Math.floor(o/1e3)}s...`)),setTimeout(s,o),o=Math.min(o*1.5,di)},c.onmessage=async l=>{try{let i=JSON.parse(l.data);if(i.type==="pair"){let m=i.target_instance_id;if(m&&m!==Z()){console.log(y.default.dim(`
128
+ \u{1F4F1} Pair event for ${i.bot_name} targets ${m} \u2014 not us, skipping`));return}console.log(y.default.cyan(`
129
+ \u{1F4F1} Pair event received: ${i.bot_name}`)),await ot(i.pair_code,i.bot_name,i.bot_user_id,!1);try{let{execSync:p}=await import("child_process");p("openclaw gateway restart",{stdio:"ignore"}),console.log(y.default.green(" \u2705 Gateway restarted \u2014 bot is live!"))}catch{console.log(y.default.dim(" Gateway restart failed \u2014 run: openclaw gateway restart"))}}else if(i.type==="gateway-restart"){console.log(y.default.cyan(`
130
+ \u{1F504} Remote gateway-restart command received`));let m=await Be();m.success?console.log(y.default.green(` \u2705 Gateway restarted: ${m.message}`)):console.log(y.default.red(` \u274C Gateway restart failed: ${m.message}`));try{await T(),console.log(y.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(y.default.dim(" Could not push heartbeat."))}}else if((i.type==="bot.delete"||i.type==="bot.disconnect")&&i.bot_user_id){let m=i.bot_user_id,p=i.type==="bot.delete"?"deleted":"disconnected",P=i.type==="bot.delete"?"\u{1F5D1}\uFE0F ":"\u{1F50C}";console.log(y.default.yellow(`
131
+ ${P} Bot ${p}: ${m} \u2014 removing from OpenClaw config...`));try{let{changed:O}=Yt(m);O?(console.log(y.default.green(" \u2705 Removed from openclaw.json")),Jt()?console.log(y.default.green(" \u2705 Gateway restarted")):console.log(y.default.dim(" Gateway restart failed \u2014 restart manually"))):console.log(y.default.dim(" Account not found in openclaw.json \u2014 nothing to remove"))}catch(O){console.log(y.default.red(` Failed to update openclaw.json: ${O}`))}}else if(i.type==="claude_code.start"&&i.bot_id&&i.room_id){console.log(y.default.cyan(`
132
+ \u{1F916} Claude Code START received: bot=${i.bot_id} room=${i.room_id}`));try{let m=await se({id:i.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:i.bot_id,room_id:i.room_id,session_id:i.session_id}});if(console.log(m.success?y.default.green(` \u2705 ${m.message}`):y.default.red(` \u274C ${m.message}`)),i.command_id)try{await L().post(`/api/v1/dashboard/commands/${i.command_id}/result`,{status:m.success?"success":"failed",result:m.message})}catch{}try{await T()}catch{}}catch(m){console.log(y.default.red(` Claude Code start error: ${m.message}`))}}else if(i.type==="claude_code.stop"&&i.bot_id&&i.room_id){console.log(y.default.cyan(`
133
+ \u{1F916} Claude Code STOP received: bot=${i.bot_id} room=${i.room_id}`));try{let m=await se({id:i.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:i.bot_id,room_id:i.room_id,session_id:i.session_id}});if(console.log(m.success?y.default.green(` \u2705 ${m.message}`):y.default.red(` \u274C ${m.message}`)),i.command_id)try{await L().post(`/api/v1/dashboard/commands/${i.command_id}/result`,{status:m.success?"success":"failed",result:m.message})}catch{}try{await T()}catch{}}catch(m){console.log(y.default.red(` Claude Code stop error: ${m.message}`))}}else if(i.type==="command.execute"&&i.command_id){console.log(y.default.cyan(`
134
+ \u26A1 SSE command received: ${i.command_type} (${i.command_id})`));try{let m=L();await m.post(`/api/v1/dashboard/commands/${i.command_id}/ack`);let p=await se({id:i.command_id,command_type:i.command_type,payload:i.payload});console.log(p.success?y.default.green(` \u2705 ${p.message}`):y.default.red(` \u274C ${p.message}`)),await m.post(`/api/v1/dashboard/commands/${i.command_id}/result`,{status:p.success?"success":"failed",result:p.message,new_version:p.newVersion||null});try{await T()}catch{}i.command_type==="update_cli"&&p.success&&(console.log(y.default.cyan(" CLI updated \u2014 restarting in 2s...")),setTimeout(()=>process.exit(0),2e3))}catch(m){console.log(y.default.red(` Command ${i.command_id} error: ${m.message}`))}}}catch{}}};s(),await new Promise(()=>{})});var as=require("commander"),d=u(require("chalk")),te=require("child_process"),R=u(require("fs")),ft=u(require("os")),ae=u(require("path"));oe();Ee();var pt=u(require("fs")),Ge=u(require("path")),Qt=require("child_process"),mi=["request","request-promise"];function pi(e){let t=e.match(/^(\s*)(?:"([^"]+)"|'([^']+)'|([^:#\s][^:]*?))\s*:/);return t?{indent:t[1].length,key:(t[2]??t[3]??t[4]??"").trim()}:null}function gi(e){let t=e.split(`
135
+ `),o=[],n=!1,r=-1,s=!1,a=new Set(mi);for(let c of t){let l=pi(c);if(!n){l&&l.indent===0&&l.key==="overrides"&&(n=!0,r=l.indent),o.push(c);continue}if(l&&l.indent<=r){n=!1,o.push(c);continue}if(l&&l.indent>r&&a.has(l.key)){s=!0;continue}o.push(c)}return s?o.join(`
136
+ `):null}function fi(){let e=[],t=(0,Qt.spawnSync)("npm",["root","-g"],{encoding:"utf-8",shell:!0});t.status===0&&t.stdout?.trim()&&e.push(Ge.default.join(t.stdout.trim(),"openclaw","pnpm-workspace.yaml"));let o=(0,Qt.spawnSync)("npm",["prefix","-g"],{encoding:"utf-8",shell:!0});o.status===0&&o.stdout?.trim()&&e.push(Ge.default.join(o.stdout.trim(),"lib","node_modules","openclaw","pnpm-workspace.yaml"));let n=(0,Qt.spawnSync)("which",["openclaw"],{encoding:"utf-8"});if(n.status===0&&n.stdout?.trim()){let r=Ge.default.dirname(Ge.default.dirname(n.stdout.trim()));e.push(Ge.default.join(r,"lib","node_modules","openclaw","pnpm-workspace.yaml"))}for(let r of e)try{if(pt.default.existsSync(r))return r}catch{}return null}function Hr(){let e=fi();if(!e)return null;let t;try{t=pt.default.readFileSync(e,"utf-8")}catch{return null}let o=gi(t);if(o===null)return null;try{pt.default.writeFileSync(e,o)}catch{return null}return{yamlPath:e,original:t}}function Ur(e){if(!e)return!1;try{return pt.default.writeFileSync(e.yamlPath,e.original),!0}catch{return!1}}_e();var qe=require("child_process"),Gr=u(require("fs")),D=u(require("chalk")),F={alreadyUp:!1,install:null,start:null,requiresRoot:!1,networkHostRequired:!1,guidance:null},Fr='On this distro the bare "docker" package is the podman shim (no dockerd). Install Docker Engine from the official docker-ce repository (https://docs.docker.com/engine/install/), then re-run `badgerclaw setup --hermes`.';function hi(e){return e.daemonUp?{...F,alreadyUp:!0}:e.host==="darwin"?e.hasDockerApp?{...F,start:"docker-app"}:e.hasColima?{...F,start:"colima"}:e.binaryPresent?{...F,guidance:"A `docker` CLI is present but no engine we can start (Docker.app / colima) was found and the daemon is not answering. Start your Docker daemon (or `colima start`), then re-run `badgerclaw setup --hermes`."}:e.hasBrew?{...F,install:{tool:"colima",via:"brew"},start:"colima"}:{...F,guidance:"No container engine found and Homebrew is absent. Install Docker Desktop (https://www.docker.com/products/docker-desktop) or Homebrew (https://brew.sh) then colima, and re-run `badgerclaw setup --hermes`."}:e.host==="linux-systemd"?e.binaryPresent?{...F,start:"systemctl",requiresRoot:!0}:e.pkgManager==="apt"?{...F,install:{tool:"docker",via:"apt"},start:"systemctl",requiresRoot:!0}:{...F,guidance:e.pkgManager?Fr:"Docker is not installed and no supported package manager (apt) was found. Install Docker, then re-run."}:e.host==="linux-nosystemd"?e.binaryPresent?{...F,start:"dockerd-restricted",requiresRoot:!0,networkHostRequired:!0}:e.pkgManager==="apt"?{...F,install:{tool:"docker",via:"apt"},start:"dockerd-restricted",requiresRoot:!0,networkHostRequired:!0}:{...F,guidance:e.pkgManager?Fr:"Docker is not installed and no supported package manager (apt) was found. Install Docker (e.g. `apt-get install -y docker.io`), then re-run."}:{...F,guidance:`Automatic Docker setup isn't supported on this platform (${process.platform}). Install + start Docker manually, then re-run.`}}function Wr(e,t,o=8e3){return(0,qe.spawnSync)(e,t,{encoding:"utf-8",timeout:o})}function tn(){let e=Wr("docker",["version","--format","{{.Server.Version}}"],4e3);return e.status===0&&!!(e.stdout||"").trim()}function yi(){return Wr("docker",["--version"],4e3).status===0}function We(e){return(0,qe.spawnSync)("sh",["-c",`command -v ${e}`],{encoding:"utf-8"}).status===0}function wi(){return We("apt-get")?"apt":We("dnf")?"dnf":We("yum")?"yum":null}function bi(){let e=(0,qe.spawnSync)("systemctl",["is-system-running"],{encoding:"utf-8",timeout:4e3});if(e.error)return!1;let t=`${e.stdout||""}${e.stderr||""}`.toLowerCase();return!/failed to connect to bus|not been booted with systemd|no such file/.test(t)}function _i(){return process.platform==="darwin"?"darwin":process.platform==="linux"?bi()?"linux-systemd":"linux-nosystemd":"unsupported"}function Si(){return typeof process.getuid=="function"?process.getuid()===0:!1}function pe(e,t){return t(D.default.dim(` $ ${e}`)),(0,qe.spawnSync)("sh",["-c",e],{stdio:"inherit"}).status===0}function ki(e,t,o){let n=t?"sudo ":"";switch(e.via){case"brew":return o(D.default.dim(" Installing colima + docker CLI via Homebrew...")),pe("brew install colima docker",o);case"apt":return o(D.default.dim(" Installing Docker via apt...")),pe(`${n}apt-get update`,o),pe(`${n}apt-get install -y docker.io`,o);default:return!1}}function vi(e,t,o){let n=t?"sudo ":"";switch(e){case"docker-app":return pe("open -a Docker",o);case"colima":return pe("colima start",o);case"systemctl":return pe(`${n}systemctl enable --now docker`,o);case"dockerd-restricted":{if(!We("dockerd"))return o(D.default.red(" \u274C `dockerd` is not installed (the docker CLI alone is not enough on a no-systemd host).")),!1;if(t&&!pe("sudo -v",o))return o(D.default.red(" \u274C root is required to start dockerd here, but sudo is unavailable.")),!1;pe(`${n}sh -c 'mount -t cgroup2 none /sys/fs/cgroup 2>/dev/null || true'`,o);let r="/tmp/badgerclaw-dockerd.log";o(D.default.dim(` Starting dockerd (restricted: --bridge=none --iptables=false) \u2192 ${r}`));let s=`nohup dockerd --storage-driver=overlay2 --iptables=false --bridge=none > ${r} 2>&1 &`,a=t?`sudo sh -c ${JSON.stringify(s)}`:`sh -c ${JSON.stringify(s)}`;return(0,qe.spawnSync)("sh",["-c",a],{stdio:"ignore"}).status===0}}}async function $i(e,t,o){let n=Date.now()+t;for(;;){if(e())return!0;if(Date.now()>=n)return!1;await new Promise(r=>setTimeout(r,o))}}async function qr(e={}){let t=e.log??(a=>console.log(a));if(process.env.BADGERCLAW_NO_AUTO_DEPS==="1"){let a=tn();return a||(t(D.default.yellow(" BADGERCLAW_NO_AUTO_DEPS=1 \u2014 skipping automatic Docker setup.")),t(D.default.dim(" Start the Docker daemon yourself, then re-run `badgerclaw setup --hermes`."))),{ok:a,daemonUp:a,networkHostRequired:!1}}let o={daemonUp:tn(),binaryPresent:yi(),host:_i(),hasBrew:We("brew"),hasDockerApp:Gr.default.existsSync("/Applications/Docker.app"),hasColima:We("colima"),pkgManager:wi(),isRoot:Si()},n=hi(o);if(n.alreadyUp)return{ok:!0,daemonUp:!0,networkHostRequired:!1};if(n.guidance)return t(D.default.red(` \u274C ${n.guidance}`)),{ok:!1,daemonUp:!1,networkHostRequired:n.networkHostRequired};let r=n.requiresRoot&&!o.isRoot;return r&&t(D.default.dim(" (some steps need root \u2014 using sudo; you may be prompted for your password)")),n.install&&!ki(n.install,r,t)?(t(D.default.red(" \u274C Docker install failed (see output above). Install it manually, then re-run.")),{ok:!1,daemonUp:!1,networkHostRequired:n.networkHostRequired}):vi(n.start,r,t)?(t(D.default.dim(" Waiting for the Docker daemon to answer...")),await $i(tn,12e4,1500)?(t(D.default.green(" \u2705 Docker daemon is up.")),{ok:!0,daemonUp:!0,networkHostRequired:n.networkHostRequired}):(t(D.default.red(" \u274C Docker did not become ready in time.")),n.start==="dockerd-restricted"?t(D.default.dim(" Check /tmp/badgerclaw-dockerd.log for the daemon output.")):n.start==="docker-app"&&t(D.default.dim(" Docker Desktop can take a minute to boot \u2014 re-run once its menu-bar icon is steady.")),{ok:!1,daemonUp:!1,networkHostRequired:n.networkHostRequired})):(t(D.default.red(" \u274C Could not start Docker (see output above). Resolve it, then re-run.")),{ok:!1,daemonUp:!1,networkHostRequired:n.networkHostRequired})}function Vr(e){let t=e.minMajor??18;if(!Number.isFinite(e.nodeMajor)||e.nodeMajor<t){let o=Number.isFinite(e.nodeMajor)?`Node v${e.nodeMajor}`:"an unknown Node version";return`badgerclaw requires Node.js >= ${t} (this is ${o}). Upgrade Node \u2014 nodesource (https://github.com/nodesource/distributions) or nvm (\`nvm install ${t}\`) \u2014 then re-run \`badgerclaw setup --hermes\`.`}return e.npmPresent?null:`npm was not found on PATH. badgerclaw is installed and updated via npm \u2014 install Node.js ${t}+ (which bundles npm) and re-run \`badgerclaw setup --hermes\`.`}function Kr(e=process.versions.node){return parseInt(String(e).split(".")[0],10)}var on=require("child_process"),Zt=u(require("fs")),Yr=u(require("os")),eo=u(require("path"));_e();De();function Ci(){let e=Jr();for(let t of e)if(Zt.default.existsSync(t))return t;return null}function Jr(){return[eo.default.resolve(__dirname,"..","assets","hermes-agent-bc.Dockerfile"),eo.default.resolve(__dirname,"..","..","assets","hermes-agent-bc.Dockerfile")]}var Ii="nousresearch/hermes-agent";function Ri(e){let t=(process.env.HERMES_UPSTREAM||e?.upstream||"").trim();if(!t)return;if(t.includes("/"))return t;let o=t.includes(":")?t.split(":").pop():t;return`${Ii}:${o}`}var xi={run:e=>{let t=(0,on.spawnSync)("docker",e,{encoding:"utf-8"});return{status:t.status,stdout:t.stdout||"",stderr:t.stderr||""}}};function Ai(e){return["build",...e.hostNetwork?["--network","host"]:[],...e.upstreamRef?["--build-arg",`UPSTREAM=${e.upstreamRef}`]:[],"-t",e.image,"-f",e.dockerfile,e.ctxDir]}function zr(e){let t=Rt();if(!t.installed)return{status:"no-docker"};let o=process.env.HERMES_IMAGE||Pe;if(xt(t).installed)return{status:"already-present",image:o};let r=Ci();if(!r)return{status:"no-dockerfile",expectedPaths:Jr()};let s=Ri(e),a=So({bridgeUsable:()=>Dt(xi)}),c=Zt.default.mkdtempSync(eo.default.join(Yr.default.tmpdir(),"bc-hermes-build-"));try{let l=(0,on.spawnSync)("docker",Ai({hostNetwork:a,upstreamRef:s,image:o,dockerfile:r,ctxDir:c}),{stdio:"inherit",timeout:6e5});return l.status===0?{status:"built",image:o}:{status:"build-failed",image:o,stderr:`docker build exited ${l.status??"<no-status>"}`}}finally{try{Zt.default.rmSync(c,{recursive:!0,force:!0})}catch{}}}M();var nn=require("child_process"),Ei="https://ollama.com/download",Pi={run:(e,t)=>{let o=(0,nn.spawnSync)(e,t,{encoding:"utf-8",timeout:1e4});return{status:o.status,stdout:o.stdout||"",stderr:o.stderr||""}}};function Xr(e={}){let t=e.runner??Pi,o=t.run("ollama",["--version"]);if(o.status!==0)return{installed:!1,serving:!1};let n=(o.stdout||"").match(/(\d+\.\d+\.\d+)/),r=n?n[1]:void 0;return{installed:!0,serving:t.run("ollama",["list"]).status===0,version:r}}function Qr(e){return e.installed?e.serving?"Ollama is installed and serving.":"Ollama is installed but its server isn't running. Start it with `ollama serve` (or open the Ollama app), then re-run setup.":`Ollama is not installed. Install it from ${Ei}, then re-run setup.`}function Zr(e,t={}){if(t.runner){let n=t.runner.run("ollama",["pull",e]);return n.status===0?{ok:!0}:{ok:!1,error:(n.stderr||n.stdout||`exit ${n.status}`).trim()}}let o=(0,nn.spawnSync)("ollama",["pull",e],{stdio:t.inheritStdio===!1?"pipe":"inherit",encoding:"utf-8"});return o.status===0?{ok:!0}:{ok:!1,error:(o.stderr||`ollama pull ${e} failed (exit ${o.status})`).toString().trim()}}var es=u(require("os")),ts=u(require("readline"));oe();De();function Di(){return Math.round(es.default.totalmem()/1024/1024/1024)}async function Oi(e,t,o={}){let n=o.apiBase??N,r=o.fetchImpl??fetch,s=`${n}/api/v1/dashboard/recommended-models?ram_gb=${encodeURIComponent(e)}&runtime=${encodeURIComponent(t)}`;try{let a=await r(s,{headers:{Accept:"application/json"}});if(!a.ok)return null;let c=await a.json(),l=c.result&&typeof c.result=="object"?c.result:c;return Array.isArray(l.recommended)?l:null}catch{return null}}async function Li(e){let t=ts.default.createInterface({input:process.stdin,output:process.stdout});try{return await new Promise(o=>t.question(e,o))}finally{t.close()}}function Ni(e){let t=e.verdict==="great"?"great":e.verdict==="usable"?"usable":e.verdict,o=e.decode_tps!=null?`${e.decode_tps} tok/s`:"speed not yet benchmarked",n=e.is_top_pick?" (recommended)":"";return`${e.model_name} [${e.ollama_tag}] \u2014 ${t}, ${o}. ${e.why}${n}`}async function Ti(e,t){let o=e.recommended;if(!o||o.length===0)return{tag:null,note:e.note,model:null};let n=o.find(i=>i.is_top_pick)??o[0];if(t.preferredTag){let i=o.find(m=>m.ollama_tag===t.preferredTag);return i?{tag:i.ollama_tag,note:e.note,model:i}:{tag:t.preferredTag,note:e.note,model:null}}if(!t.interactive)return{tag:n.ollama_tag,note:e.note,model:n};let r=t.log??(i=>console.log(i)),s=t.prompt??Li;r(`
137
+ Local models that fit ${e.ram_gb} GB (${e.ram_tier}):`),o.forEach((i,m)=>{r(` ${i===n?"*":" "} ${m+1}) ${Ni(i)}`)});let a=o.indexOf(n)+1,c=(await s(` Pick a model [${a}]: `)).trim();if(!c)return{tag:n.ollama_tag,note:e.note,model:n};let l=Number.parseInt(c,10);if(Number.isInteger(l)&&l>=1&&l<=o.length){let i=o[l-1];return{tag:i.ollama_tag,note:e.note,model:i}}return{tag:n.ollama_tag,note:e.note,model:n}}async function os(e){let t=e.ramGb??Di(),o=await Oi(t,e.runtime,{apiBase:e.apiBase,fetchImpl:e.fetchImpl});if(!o)return{tag:e.preferredTag||_o("ollama"),note:"Could not reach the model-recommendation service \u2014 using a safe default model.",ramGb:t,fellBack:!0};let n=await Ti(o,{interactive:e.interactive,preferredTag:e.preferredTag,prompt:e.prompt,log:e.log});return{tag:n.tag,note:n.note,ramGb:t,fellBack:!1}}De();var z=ae.default.join(ft.default.homedir(),".openclaw","openclaw.json"),gt=z+".badgerclaw-stash",is=ae.default.join(ft.default.homedir(),".openclaw","npm"),Mi=ae.default.join(is,"package.json");async function ns(){try{let e=await fetch(`${N}/api/v1/dashboard/versions/latest`,{headers:{Accept:"application/json"}});if(!e.ok)return{cli:null,plugin:null,openclaw:null,hermes:null};let t=await e.json(),o=t.result&&typeof t.result=="object"?t.result:t,n=r=>typeof r!="string"||!r||r==="unknown"?null:r;return{cli:n(o.cli),plugin:n(o.plugin),openclaw:n(o.supported_openclaw),hermes:n(o.supported_hermes)}}catch{return{cli:null,plugin:null,openclaw:null,hermes:null}}}function Bi(){if(!R.default.existsSync(z))return null;try{let e=JSON.parse(R.default.readFileSync(z,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,R.default.writeFileSync(z,JSON.stringify(e,null,2)),R.default.writeFileSync(gt,JSON.stringify(t,null,2)),t):null}catch{return null}}function ji(){if(!R.default.existsSync(z))return null;try{let e=JSON.parse(R.default.readFileSync(z,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function Hi(e){if(e&&R.default.existsSync(z))try{let t=JSON.parse(R.default.readFileSync(z,"utf-8"));t.gateway={...e,...t.gateway||{}},R.default.writeFileSync(z,JSON.stringify(t,null,2))}catch(t){console.log(d.default.yellow(` \u26A0\uFE0F Could not restore gateway block: ${t.message}`)),console.log(d.default.yellow(" Run `openclaw config set gateway.mode local` manually if the gateway fails to start."))}}function Ui(){if(R.default.existsSync(gt))try{let e=JSON.parse(R.default.readFileSync(gt,"utf-8")),t=JSON.parse(R.default.readFileSync(z,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,R.default.writeFileSync(z,JSON.stringify(t,null,2)),R.default.unlinkSync(gt)}catch(e){console.log(d.default.yellow(` \u26A0\uFE0F Could not restore config: ${e.message}`)),console.log(d.default.yellow(` Your bot credentials are backed up at: ${gt}`))}}async function rs(e){return new Promise(t=>{let o=(0,te.spawn)("openclaw",["plugins","install",e,"--force","--dangerously-force-unsafe-install"],{stdio:["ignore","pipe","pipe"],shell:!0}),n="",r=!1,s=!1,a=/Installed plugin:|Restart the gateway to load plugins/,c=()=>{r||s||(r=!0,setTimeout(()=>{if(!s){try{o.kill("SIGTERM")}catch{}setTimeout(()=>{if(!s)try{o.kill("SIGKILL")}catch{}},1e3)}},3e3))},l=(i,m)=>{m.write(i),n+=i.toString("utf-8"),a.test(n)&&c()};o.stdout.on("data",i=>l(i,process.stdout)),o.stderr.on("data",i=>l(i,process.stderr)),o.on("exit",i=>{s=!0,t({status:r?0:i??1})}),o.on("error",i=>{s||(s=!0,console.error(d.default.red(` openclaw spawn error: ${i.message}`)),t({status:1}))})})}function ss(e){if(!R.default.existsSync(e))return!1;let t;try{t=JSON.parse(R.default.readFileSync(e,"utf-8"))}catch{return!1}let o=!1;return t.overrides&&typeof t.overrides=="object"&&"uuid"in t.overrides&&(delete t.overrides.uuid,o=!0),t.openclaw&&Array.isArray(t.openclaw.managedOverrides)&&t.openclaw.managedOverrides.includes("uuid")&&(t.openclaw.managedOverrides=t.openclaw.managedOverrides.filter(n=>n!=="uuid"),o=!0),o?(R.default.writeFileSync(e,JSON.stringify(t,null,2)+`
138
+ `),!0):!1}function Fi(){let e=[];ss(Mi)&&e.push(is);for(let t of Ct())ss(ae.default.join(t,"package.json"))&&e.push(t);return e}async function Gi(){let{detectCapabilities:e}=await Promise.resolve().then(()=>(_e(),Ln)),{pushHeartbeat:t}=await Promise.resolve().then(()=>(je(),zo));console.log(d.default.green(`
137
139
  \u{1F9A1} BadgerClaw \u2014 capability refresh
138
- `));let o=e();console.log(u.default.dim(" Detected on this host:")),console.log(u.default.dim(` OpenClaw : ${en(o.openclaw)}`)),console.log(u.default.dim(` Hermes : ${en(o.hermes)}`)),console.log(u.default.dim(` Docker : ${en(o.docker)}`)),o.disk_free_gb!==null&&console.log(u.default.dim(` Disk free: ${o.disk_free_gb} GB`));try{await t(),console.log(u.default.green(`
139
- \u2705 Capabilities pushed to the API.`)),console.log(u.default.dim(" The backend will route new bot assignments accordingly."))}catch(n){let r=n?.message||String(n);if(r.includes("no auth")||r.includes("401")){console.log(u.default.yellow(`
140
- \u26A0\uFE0F Not logged in \u2014 capabilities re-scanned locally but not posted to the API.`)),console.log(u.default.dim(" Run `badgerclaw login` first, then re-run `badgerclaw setup --refresh`."));return}console.log(u.default.red(`
141
- \u274C Failed to push capabilities: ${r}`)),process.exit(1)}}function en(e){return e.installed?e.version?`installed (${e.version})`:e.image?`installed (${e.image})`:"installed":"not installed"}var Xr=new Yr.Command("setup").description("Install or update the OpenClaw BadgerClaw plugin safely (handles config automatically)").option("--refresh","Skip install steps; re-scan host capabilities and push them to the API immediately. Useful right after installing a second runtime (Docker, Hermes image) so the backend doesn't have to wait for the next heartbeat tick to pick up the change.").option("--hermes","Opt this host into the Hermes runtime instead of OpenClaw. Skips the OpenClaw binary + plugin + gateway install entirely; instead builds the Hermes container image locally from the bundled Dockerfile (against the public nousresearch/hermes-agent base on Docker Hub \u2014 no AWS/ECR credentials needed). Default (no flag) installs OpenClaw \u2014 Hermes is opt-in while it's still being soaked on early-adopter hosts.").action(async e=>{if(e.refresh){await Ci();return}if(console.log(u.default.green(`
140
+ `));let o=e();console.log(d.default.dim(" Detected on this host:")),console.log(d.default.dim(` OpenClaw : ${rn(o.openclaw)}`)),console.log(d.default.dim(` Hermes : ${rn(o.hermes)}`)),console.log(d.default.dim(` Docker : ${rn(o.docker)}`)),o.disk_free_gb!==null&&console.log(d.default.dim(` Disk free: ${o.disk_free_gb} GB`));try{await t(),console.log(d.default.green(`
141
+ \u2705 Capabilities pushed to the API.`)),console.log(d.default.dim(" The backend will route new bot assignments accordingly."))}catch(n){let r=n?.message||String(n);if(r.includes("no auth")||r.includes("401")){console.log(d.default.yellow(`
142
+ \u26A0\uFE0F Not logged in \u2014 capabilities re-scanned locally but not posted to the API.`)),console.log(d.default.dim(" Run `badgerclaw login` first, then re-run `badgerclaw setup --refresh`."));return}console.log(d.default.red(`
143
+ \u274C Failed to push capabilities: ${r}`)),process.exit(1)}}function rn(e){return e.installed?e.version?`installed (${e.version})`:e.image?`installed (${e.image})`:"installed":"not installed"}async function Wi(e){console.log(d.default.green(`
144
+ \u{1F9E0} Local LLM (Ollama/Qwen) \u2014 RAM-aware model picker
145
+ `));let t=process.stdout.isTTY===!0&&process.stdin.isTTY===!0&&!e.assumeYes,o=process.env.BADGERCLAW_LLM_MODEL||void 0,n=await os({runtime:"hermes",interactive:t,preferredTag:o,log:a=>console.log(d.default.dim(a))});if(console.log(d.default.dim(` Detected RAM: ~${n.ramGb} GB`)),!n.tag){console.log(d.default.yellow(`
146
+ \u26A0\uFE0F ${n.note||"Your RAM is too low for a usable local model."}`)),console.log(d.default.dim(" Falling back to the normal cloud-LLM path. Set GOOGLE_API_KEY / ANTHROPIC_API_KEY / OPENROUTER_API_KEY (or BADGERCLAW_LLM_PROVIDER + BADGERCLAW_LLM_API_KEY) before pairing a bot."));return}n.fellBack&&n.note&&console.log(d.default.yellow(` \u26A0\uFE0F ${n.note}`)),console.log(d.default.dim(` Selected local model: ${d.default.cyan(n.tag)}`));let r=Xr();if(!r.installed||!r.serving){console.log(d.default.yellow(`
147
+ \u26A0\uFE0F ${Qr(r)}`)),console.log(d.default.dim(" Local-LLM setup can't continue without Ollama. Falling back to the cloud-LLM path; install/start Ollama and re-run `badgerclaw setup --hermes --local-llm` to switch this host to a local model."));return}console.log(d.default.dim(` Ollama ${r.version||""} detected and serving.`)),console.log(d.default.dim(` Pulling ${n.tag} via Ollama (one-time, can be large)...`));let s=Zr(n.tag);s.ok||(console.log(d.default.red(`
148
+ \u274C Failed to pull ${n.tag}: ${s.error}`)),console.log(d.default.dim(` Pull it manually with \`ollama pull ${n.tag}\`, then re-run setup.`)),process.exit(1)),console.log(d.default.green(` \u2705 Model ${n.tag} ready.`)),jn({provider:"ollama",model:n.tag}),console.log(d.default.green(" \u2705 This host will use the local Ollama model for new Hermes bots."))}var ls=new as.Command("setup").description("Install or update the OpenClaw BadgerClaw plugin safely (handles config automatically)").option("--refresh","Skip install steps; re-scan host capabilities and push them to the API immediately. Useful right after installing a second runtime (Docker, Hermes image) so the backend doesn't have to wait for the next heartbeat tick to pick up the change.").option("--hermes","Opt this host into the Hermes runtime instead of OpenClaw. Skips the OpenClaw binary + plugin + gateway install entirely; instead builds the Hermes container image locally from the bundled Dockerfile (against the public nousresearch/hermes-agent base on Docker Hub \u2014 no AWS/ECR credentials needed). Default (no flag) installs OpenClaw \u2014 Hermes is opt-in while it's still being soaked on early-adopter hosts.").option("--local-llm","Use a local LLM (Ollama/Qwen) for this host instead of a cloud provider. Hermes only. Detects this host's RAM, asks the backend which Qwen models fit, lets you pick one (or auto-picks the best fit in non-interactive runs), then pulls it via Ollama and wires Hermes to talk to 127.0.0.1:11434. Also engaged implicitly by BADGERCLAW_LLM_PROVIDER=ollama. Requires Ollama installed + serving (we never auto-install it). When RAM is too low for any usable local model, setup tells you and falls back to the normal cloud path.").option("--yes","Assume defaults for any interactive prompt (e.g. the local-LLM model picker auto-selects the recommended model). Useful for scripted / unattended runs.").action(async e=>{if(e.refresh){await Gi();return}if(console.log(d.default.green(`
142
149
  \u{1F9A1} BadgerClaw Setup
143
- `)),Cr({hermes:e.hermes})==="hermes"){let f=Ur({nodeMajor:Fr(),npmPresent:(0,te.spawnSync)("sh",["-c","command -v npm"],{encoding:"utf-8"}).status===0});f&&(console.log(u.default.red(`
144
- \u274C ${f}`)),process.exit(1));let v=le();if(console.log(u.default.dim(` Detected: Docker ${v.docker.installed?"running":"not running"}, Hermes image ${v.hermes.installed?"present":"absent"}.`)),console.log(u.default.dim(` Selected runtime: ${u.default.cyan("hermes")} (via --hermes flag)
145
- `)),!v.docker.installed){console.log(u.default.dim(" Docker is not ready \u2014 bootstrapping it for the Hermes runtime..."));let b=await Hr({log:w=>console.log(w)});b.ok||(console.log(u.default.red(`
146
- \u274C Docker is required for the Hermes runtime and could not be started automatically.`)),console.log(u.default.dim(" Resolve the issue above (or set Docker up manually), then re-run `badgerclaw setup --hermes`.")),process.exit(1)),b.networkHostRequired&&console.log(u.default.dim(" \u24D8 No Docker bridge on this host \u2014 Hermes bots will use host networking automatically at pair time.")),v=le()}if(v.disk_free_gb!==null&&v.disk_free_gb<6&&console.log(u.default.yellow(` \u26A0\uFE0F Low disk: ${v.disk_free_gb} GB free \u2014 the Hermes image build needs ~5 GB and may fail if it runs out.`)),v.hermes.installed)console.log(u.default.dim(` Hermes image already present: ${v.hermes.image}`));else{let b=(await Vr()).hermes;b&&console.log(u.default.dim(` Pinned Hermes upstream: ${b}`)),console.log(u.default.dim(" Building Hermes image (one-time, ~2 min)..."));let w=qr({upstream:b});w.status==="built"?console.log(u.default.green(` \u2705 Hermes image built: ${w.image}`)):w.status==="already-present"?console.log(u.default.dim(` Hermes image already present: ${w.image}`)):w.status==="no-dockerfile"?(console.log(u.default.red(`
147
- \u274C Bundled Hermes Dockerfile missing from CLI install.`)),console.log(u.default.dim(" Reinstall: npm install -g badgerclaw@latest")),console.log(u.default.dim(` Looked at: ${w.expectedPaths.join(", ")}`)),process.exit(1)):w.status==="build-failed"?(console.log(u.default.red(`
148
- \u274C Hermes image build failed: ${w.stderr}`)),console.log(u.default.dim(" See the docker output above for details.")),process.exit(1)):w.status==="no-docker"&&(console.log(u.default.red(`
149
- \u274C Docker is not running.`)),process.exit(1))}console.log(u.default.dim(`
150
- Cleaning up heartbeat hooks from previous installs...`)),Zn({loggedIn:_()!==null,log:b=>console.log(u.default.dim(` ${b}`))}),console.log(u.default.dim(`
150
+ `)),Er({hermes:e.hermes})==="hermes"){let f=Vr({nodeMajor:Kr(),npmPresent:(0,te.spawnSync)("sh",["-c","command -v npm"],{encoding:"utf-8"}).status===0});f&&(console.log(d.default.red(`
151
+ \u274C ${f}`)),process.exit(1));let v=ce();if(console.log(d.default.dim(` Detected: Docker ${v.docker.installed?"running":"not running"}, Hermes image ${v.hermes.installed?"present":"absent"}.`)),console.log(d.default.dim(` Selected runtime: ${d.default.cyan("hermes")} (via --hermes flag)
152
+ `)),!v.docker.installed){console.log(d.default.dim(" Docker is not ready \u2014 bootstrapping it for the Hermes runtime..."));let _=await qr({log:w=>console.log(w)});_.ok||(console.log(d.default.red(`
153
+ \u274C Docker is required for the Hermes runtime and could not be started automatically.`)),console.log(d.default.dim(" Resolve the issue above (or set Docker up manually), then re-run `badgerclaw setup --hermes`.")),process.exit(1)),_.networkHostRequired&&console.log(d.default.dim(" \u24D8 No Docker bridge on this host \u2014 Hermes bots will use host networking automatically at pair time.")),v=ce()}if(v.disk_free_gb!==null&&v.disk_free_gb<6&&console.log(d.default.yellow(` \u26A0\uFE0F Low disk: ${v.disk_free_gb} GB free \u2014 the Hermes image build needs ~5 GB and may fail if it runs out.`)),v.hermes.installed)console.log(d.default.dim(` Hermes image already present: ${v.hermes.image}`));else{let _=(await ns()).hermes;_&&console.log(d.default.dim(` Pinned Hermes upstream: ${_}`)),console.log(d.default.dim(" Building Hermes image (one-time, ~2 min)..."));let w=zr({upstream:_});w.status==="built"?console.log(d.default.green(` \u2705 Hermes image built: ${w.image}`)):w.status==="already-present"?console.log(d.default.dim(` Hermes image already present: ${w.image}`)):w.status==="no-dockerfile"?(console.log(d.default.red(`
154
+ \u274C Bundled Hermes Dockerfile missing from CLI install.`)),console.log(d.default.dim(" Reinstall: npm install -g badgerclaw@latest")),console.log(d.default.dim(` Looked at: ${w.expectedPaths.join(", ")}`)),process.exit(1)):w.status==="build-failed"?(console.log(d.default.red(`
155
+ \u274C Hermes image build failed: ${w.stderr}`)),console.log(d.default.dim(" See the docker output above for details.")),process.exit(1)):w.status==="no-docker"&&(console.log(d.default.red(`
156
+ \u274C Docker is not running.`)),process.exit(1))}(e.localLlm===!0||(process.env.BADGERCLAW_LLM_PROVIDER||"").toLowerCase()==="ollama")&&await Wi({assumeYes:e.yes===!0}),console.log(d.default.dim(`
157
+ Cleaning up heartbeat hooks from previous installs...`)),rr({loggedIn:b()!==null,log:_=>console.log(d.default.dim(` ${_}`))}),console.log(d.default.dim(`
151
158
  Hermes-only mode \u2014 skipping OpenClaw plugin + gateway install.
152
159
  To enable OC bots later, drop the --hermes flag: \`badgerclaw setup\`.
153
- `)),console.log(u.default.green("\u2705 Setup complete (Hermes-only host).")),console.log(u.default.dim("\nNext steps:\n 1. `badgerclaw login` \u2014 authenticate this CLI to the backend.\n 2. `badgerclaw setup --refresh` \u2014 push the Hermes capability so\n the backend (and the iOS app) knows this host can serve\n Hermes bots.\n 3. `badgerclaw bot create <name>` \u2014 defaults to Hermes on this host."));return}let o=await Vr();if(o.cli){let f=po();f!==o.cli?(console.log(u.default.dim(` Updating CLI: ${f} \u2192 ${o.cli} (supported)...`)),(0,te.spawnSync)("npm",["install","-g",`badgerclaw@${o.cli}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red("\n\u274C CLI update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(u.default.green(` \u2705 CLI updated to ${o.cli}`))):console.log(u.default.dim(` CLI already at approved version ${f}.`))}if(o.openclaw){let f=G();f!==o.openclaw?(console.log(f===null?u.default.dim(` Installing OpenClaw ${o.openclaw} (supported)...`):u.default.dim(` Updating OpenClaw: ${f} \u2192 ${o.openclaw} (supported)...`)),(0,te.spawnSync)("npm",["install","-g",`openclaw@${o.openclaw}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red("\n\u274C OpenClaw install/update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(u.default.green(` \u2705 OpenClaw at ${o.openclaw}`))):console.log(u.default.dim(` OpenClaw already at approved version ${f}.`))}else G()===null&&(console.log(u.default.yellow(" \u26A0\uFE0F No approved OpenClaw version and none installed \u2014 installing latest from npm.")),(0,te.spawnSync)("npm",["install","-g","openclaw"],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red(`
154
- \u274C OpenClaw install failed.`)),process.exit(1)));let n=_i();n&&console.log(u.default.dim(" Existing bot config stashed temporarily..."));let r=Si();(0,te.spawnSync)("openclaw",["gateway","stop"],{stdio:"pipe",shell:!0,timeout:1e4});let s=[se.default.join(pt.default.homedir(),".openclaw","extensions","badgerclaw"),se.default.join(pt.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),...vt()],a=[],c=[],i=f=>{let v=`${f}.bc-setup-stash-${Date.now()}-${Math.floor(Math.random()*1e6)}`,b=(0,te.spawnSync)("mv",["-f",f,v],{encoding:"utf-8"});return b.status===0?{ok:!0,stash:v}:{ok:!1,error:(b.stderr||"").trim()||`exit ${b.status}`}};for(let f of s)if(I.default.existsSync(f))try{I.default.rmSync(f,{recursive:!0,force:!0}),a.push(f)}catch(v){let b=i(f);b.ok?(c.push(`${f} \u2192 ${b.stash}`),console.log(u.default.yellow(` \u26A0\uFE0F Could not delete ${f} (${v.message}); renamed it aside instead.`))):(console.log(u.default.red(` \u274C Could not delete ${f} (${v.message})`)),console.log(u.default.red(` Could not rename ${f} aside either (${b.error}). Plugin install will likely fail.`)))}a.length>0&&console.log(u.default.dim(` Cleared existing plugin director${a.length>1?"ies":"y"}.`)),c.length>0&&console.log(u.default.dim(` Renamed busy install${c.length>1?"s":""} aside: ${c.join(", ")}`));let l=o.plugin?`@badgerclaw/connect@${o.plugin}`:"@badgerclaw/connect";o.plugin?console.log(u.default.dim(` Installing ${l} (supported)...`)):console.log(u.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let m=null;$n("2026.6.5")&&(m=Tr(),m&&console.log(u.default.dim(" Adjusted OpenClaw 2026.6.5 npm overrides for a full channel-plugin install.")));let p=await Kr(l);if(p.status===0&&o.plugin&&o.plugin!=="unknown"){for(let v=1;v<=2&&!($t()===o.plugin||(console.log(u.default.yellow(` Plugin landed as a hook-pack-only install (not yet visible to \`badgerclaw login\`) \u2014 re-running plugin install (attempt ${v}/2)...`)),p=await Kr(l),p.status!==0));v++);p.status===0&&$t()!==o.plugin&&console.log(u.default.yellow(" \u26A0\uFE0F Plugin still not detected at the npm install path after 2 attempt(s). If `badgerclaw login` reports it as not installed, re-run `badgerclaw setup`."))}n&&(vi(),console.log(u.default.dim(" Bot config restored."))),r&&(ki(r),console.log(u.default.dim(" Gateway config restored."))),m&&Lr(m),p.status!==0&&(console.log(u.default.red(`
155
- \u274C Plugin install failed. Your bot config has been restored.`)),process.exit(1)),console.log(u.default.green(`
156
- \u2705 BadgerClaw plugin installed successfully!`));let E=$i();for(let f of E){console.log(u.default.dim(` Stripping OpenClaw uuid:14 override in ${f} (breaks request@2.88 in matrix-bot-sdk)...`));try{I.default.rmSync(se.default.join(f,"node_modules","uuid"),{recursive:!0,force:!0})}catch{}try{I.default.rmSync(se.default.join(f,"package-lock.json"),{force:!0})}catch{}(0,te.spawnSync)("npm",["install"],{cwd:f,stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red(`
157
- \u274C npm install failed after removing uuid override. Bot will not reply correctly until this is resolved.`)),process.exit(1))}E.length>0&&console.log(u.default.green(" \u2705 uuid override stripped + npm tree re-resolved.")),console.log("");let D=await jt({verbose:!0});D.ok||(console.log(u.default.red(`
158
- \u274C Gateway failed to start. Diagnose with:`)),console.log(u.default.dim(" systemctl --user status openclaw-gateway.service # Linux")),console.log(u.default.dim(" launchctl list | grep openclaw # macOS")),console.log(u.default.dim(" openclaw config get gateway.mode")),console.log(u.default.dim(" Then re-run `badgerclaw setup` after fixing the underlying issue.")),process.exit(1)),D.ready===!1?console.log(u.default.yellow(" \u23F3 Gateway started but not answering yet \u2014 it may still be coming up.")):console.log(u.default.green(" \u2705 Gateway is running.")),console.log(u.default.dim("\nNext: run `badgerclaw login` to authenticate.")),Mt()});Be();var Zr=require("commander"),A=d(require("chalk"));L();xe();ue();var es=new Zr.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{_()||(console.log(A.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=be(),o=bt(),n=await at();console.log(A.default.bold.green(`
160
+ `)),console.log(d.default.green("\u2705 Setup complete (Hermes-only host).")),console.log(d.default.dim("\nNext steps:\n 1. `badgerclaw login` \u2014 authenticate this CLI to the backend.\n 2. `badgerclaw setup --refresh` \u2014 push the Hermes capability so\n the backend (and the iOS app) knows this host can serve\n Hermes bots.\n 3. `badgerclaw bot create <name>` \u2014 defaults to Hermes on this host."));return}let o=await ns();if(o.cli){let f=go();f!==o.cli?(console.log(d.default.dim(` Updating CLI: ${f} \u2192 ${o.cli} (supported)...`)),(0,te.spawnSync)("npm",["install","-g",`badgerclaw@${o.cli}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(d.default.red("\n\u274C CLI update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(d.default.green(` \u2705 CLI updated to ${o.cli}`))):console.log(d.default.dim(` CLI already at approved version ${f}.`))}if(o.openclaw){let f=G();f!==o.openclaw?(console.log(f===null?d.default.dim(` Installing OpenClaw ${o.openclaw} (supported)...`):d.default.dim(` Updating OpenClaw: ${f} \u2192 ${o.openclaw} (supported)...`)),(0,te.spawnSync)("npm",["install","-g",`openclaw@${o.openclaw}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(d.default.red("\n\u274C OpenClaw install/update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(d.default.green(` \u2705 OpenClaw at ${o.openclaw}`))):console.log(d.default.dim(` OpenClaw already at approved version ${f}.`))}else G()===null&&(console.log(d.default.yellow(" \u26A0\uFE0F No approved OpenClaw version and none installed \u2014 installing latest from npm.")),(0,te.spawnSync)("npm",["install","-g","openclaw"],{stdio:"inherit",shell:!0}).status!==0&&(console.log(d.default.red(`
161
+ \u274C OpenClaw install failed.`)),process.exit(1)));let n=Bi();n&&console.log(d.default.dim(" Existing bot config stashed temporarily..."));let r=ji();(0,te.spawnSync)("openclaw",["gateway","stop"],{stdio:"pipe",shell:!0,timeout:1e4});let s=[ae.default.join(ft.default.homedir(),".openclaw","extensions","badgerclaw"),ae.default.join(ft.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),...Ct()],a=[],c=[],l=f=>{let v=`${f}.bc-setup-stash-${Date.now()}-${Math.floor(Math.random()*1e6)}`,I=(0,te.spawnSync)("mv",["-f",f,v],{encoding:"utf-8"});return I.status===0?{ok:!0,stash:v}:{ok:!1,error:(I.stderr||"").trim()||`exit ${I.status}`}};for(let f of s)if(R.default.existsSync(f))try{R.default.rmSync(f,{recursive:!0,force:!0}),a.push(f)}catch(v){let I=l(f);I.ok?(c.push(`${f} \u2192 ${I.stash}`),console.log(d.default.yellow(` \u26A0\uFE0F Could not delete ${f} (${v.message}); renamed it aside instead.`))):(console.log(d.default.red(` \u274C Could not delete ${f} (${v.message})`)),console.log(d.default.red(` Could not rename ${f} aside either (${I.error}). Plugin install will likely fail.`)))}a.length>0&&console.log(d.default.dim(` Cleared existing plugin director${a.length>1?"ies":"y"}.`)),c.length>0&&console.log(d.default.dim(` Renamed busy install${c.length>1?"s":""} aside: ${c.join(", ")}`));let i=o.plugin?`@badgerclaw/connect@${o.plugin}`:"@badgerclaw/connect";o.plugin?console.log(d.default.dim(` Installing ${i} (supported)...`)):console.log(d.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let m=null;xn("2026.6.5")&&(m=Hr(),m&&console.log(d.default.dim(" Adjusted OpenClaw 2026.6.5 npm overrides for a full channel-plugin install.")));let p=await rs(i);if(p.status===0&&o.plugin&&o.plugin!=="unknown"){for(let v=1;v<=2&&!(It()===o.plugin||(console.log(d.default.yellow(` Plugin landed as a hook-pack-only install (not yet visible to \`badgerclaw login\`) \u2014 re-running plugin install (attempt ${v}/2)...`)),p=await rs(i),p.status!==0));v++);p.status===0&&It()!==o.plugin&&console.log(d.default.yellow(" \u26A0\uFE0F Plugin still not detected at the npm install path after 2 attempt(s). If `badgerclaw login` reports it as not installed, re-run `badgerclaw setup`."))}n&&(Ui(),console.log(d.default.dim(" Bot config restored."))),r&&(Hi(r),console.log(d.default.dim(" Gateway config restored."))),m&&Ur(m),p.status!==0&&(console.log(d.default.red(`
162
+ \u274C Plugin install failed. Your bot config has been restored.`)),process.exit(1)),console.log(d.default.green(`
163
+ \u2705 BadgerClaw plugin installed successfully!`));let P=Fi();for(let f of P){console.log(d.default.dim(` Stripping OpenClaw uuid:14 override in ${f} (breaks request@2.88 in matrix-bot-sdk)...`));try{R.default.rmSync(ae.default.join(f,"node_modules","uuid"),{recursive:!0,force:!0})}catch{}try{R.default.rmSync(ae.default.join(f,"package-lock.json"),{force:!0})}catch{}(0,te.spawnSync)("npm",["install"],{cwd:f,stdio:"inherit",shell:!0}).status!==0&&(console.log(d.default.red(`
164
+ \u274C npm install failed after removing uuid override. Bot will not reply correctly until this is resolved.`)),process.exit(1))}P.length>0&&console.log(d.default.green(" \u2705 uuid override stripped + npm tree re-resolved.")),console.log("");let O=await jt({verbose:!0});O.ok||(console.log(d.default.red(`
165
+ \u274C Gateway failed to start. Diagnose with:`)),console.log(d.default.dim(" systemctl --user status openclaw-gateway.service # Linux")),console.log(d.default.dim(" launchctl list | grep openclaw # macOS")),console.log(d.default.dim(" openclaw config get gateway.mode")),console.log(d.default.dim(" Then re-run `badgerclaw setup` after fixing the underlying issue.")),process.exit(1)),O.ready===!1?console.log(d.default.yellow(" \u23F3 Gateway started but not answering yet \u2014 it may still be coming up.")):console.log(d.default.green(" \u2705 Gateway is running.")),console.log(d.default.dim("\nNext: run `badgerclaw login` to authenticate.")),Ht()});je();var ds=require("commander"),E=u(require("chalk"));M();xe();ue();var us=new ds.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{b()||(console.log(E.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=be(),o=St(),n=await lt();console.log(E.default.bold.green(`
159
166
  BadgerClaw Dashboard
160
- `)),console.log(A.default.bold(" Instance")),console.log(` ID: ${Q()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${n.pluginVersion}`),console.log(),console.log(A.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${Qr(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let r=n.status==="running"?A.default.green:n.status==="error"?A.default.red:A.default.yellow;if(console.log(A.default.bold(" Gateway")),console.log(` Status: ${r(n.status)}`),console.log(` PID: ${n.pid??"N/A"}`),console.log(` Last Restart: ${n.lastRestart??"N/A"}`),console.log(),n.bots.length===0)console.log(A.default.bold(" Bots")),console.log(A.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log(A.default.bold(` Bots (${n.bots.length})`)),console.log();for(let s of n.bots){let a=s.status==="running"?A.default.green:s.status==="error"?A.default.red:A.default.yellow;if(console.log(` ${A.default.bold(s.botUsername)} ${a(`[${s.status}]`)}`),console.log(` ID: ${s.botId}`),console.log(` Uptime: ${Qr(s.uptimeSeconds)}`),console.log(` Messages: ${s.messagesReceived} in / ${s.messagesSent} out`),s.chunkedMessages>0&&console.log(` Chunked: ${s.chunkedMessages} messages, ${s.totalChunksSent} chunks`),console.log(` Rooms: ${s.roomsActive} active`),console.log(` Errors: ${s.errors}`),s.lastError&&(console.log(` Last Error: ${A.default.red(s.lastError)}`),console.log(` Error At: ${s.lastErrorAt}`)),console.log(` Last Active: ${s.lastActivity??"N/A"}`),s.roomDetails&&s.roomDetails.length>0){console.log(A.default.dim(" Rooms:"));for(let c of s.roomDetails)console.log(A.default.dim(` ${c.roomName} \u2014 ${c.messagesInRoom} msgs, last: ${c.lastActivityInRoom??"N/A"}`))}console.log()}}console.log(A.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function Qr(e){if(e<60)return`${e}s`;if(e<3600)return`${Math.floor(e/60)}m ${e%60}s`;let t=Math.floor(e/3600),o=Math.floor(e%3600/60);return t<24?`${t}h ${o}m`:`${Math.floor(t/24)}d ${t%24}h ${o}m`}var tn=require("commander"),We=d(require("chalk")),ts=d(require("ora"));L();ue();Be();var Ii=new tn.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{_()||(console.log(We.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,ts.default)("Restarting gateway...").start(),o=await Le();if(o.success){t.succeed(We.default.green(`Gateway restarted: ${o.message}`));try{await T(),console.log(We.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(We.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(We.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),os=new tn.Command("gateway").description("Manage the OpenClaw gateway").addCommand(Ii);var fe=require("commander"),k=d(require("chalk")),Ie=d(require("ora")),ge=d(require("axios"));Ft();L();var Ce="http://localhost:7331",xi=new fe.Command("start").description("Start a Claude Code session for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID (default: auto-generated)").option("--port <port>","MCP server port (default: 7332)","7332").option("--project <dir>","Project directory",process.cwd()).action(async e=>{_()||(console.log(k.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=e.sessionId||`session-${Date.now()}`,n=parseInt(e.port,10),r=e.project.replace(/^~/,process.env.HOME||""),s=(0,Ie.default)("Starting Claude Code session...").start();try{await ge.default.post(`${Ce}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),s.text="Gateway toggled \u2014 launching MCP server...";let c=jo({sessionId:o,port:n,projectDir:r}).pid||0;await new Promise(i=>setTimeout(i,1500)),s.text="MCP server running \u2014 launching Claude Code...",Mo({sessionId:o,port:n,projectDir:r}),Ho(o,0,c,n,r),s.succeed(k.default.green("Claude Code session started")+k.default.dim(` (session: ${o}, port: ${n})`)),console.log(k.default.dim(` Bot: ${e.bot}`)),console.log(k.default.dim(` Room: ${e.room}`)),console.log(k.default.dim(` Project: ${r}`)),console.log(k.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let c=a.response?.data?.message||a.message||"Unknown error";s.fail(k.default.red(`Failed to start Claude Code: ${c}`)),process.exit(1)}}),Ri=new fe.Command("stop").description("Stop a Claude Code session").option("--bot <botId>","Bot ID or username").option("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID to stop").action(async e=>{_()||(console.log(k.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,Ie.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await ge.default.post(`${Ce}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let n=e.sessionId;if(!n)try{let a=((await ge.default.get(`${Ce}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(c=>c.botId===e.bot&&c.roomId===e.room);a&&(n=a.sessionId)}catch{}n?(Uo(n),o.succeed(k.default.green(`Claude Code session stopped (${n})`))):(o.succeed(k.default.green("Claude Code toggled off at gateway")),console.log(k.default.dim(" No local session found to kill \u2014 may need to close Claude Code manually.")))}catch(n){let r=n.response?.data?.message||n.message||"Unknown error";o.fail(k.default.red(`Failed to stop Claude Code: ${r}`)),process.exit(1)}}),Ai=new fe.Command("status").description("Show active Claude Code sessions").action(async()=>{_()||(console.log(k.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,Ie.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await ge.default.get(`${Ce}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let n=Fo();if(t.stop(),o.length===0&&n.length===0){console.log(k.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(k.default.bold(`
167
+ `)),console.log(E.default.bold(" Instance")),console.log(` ID: ${Z()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${n.pluginVersion}`),console.log(),console.log(E.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${cs(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let r=n.status==="running"?E.default.green:n.status==="error"?E.default.red:E.default.yellow;if(console.log(E.default.bold(" Gateway")),console.log(` Status: ${r(n.status)}`),console.log(` PID: ${n.pid??"N/A"}`),console.log(` Last Restart: ${n.lastRestart??"N/A"}`),console.log(),n.bots.length===0)console.log(E.default.bold(" Bots")),console.log(E.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log(E.default.bold(` Bots (${n.bots.length})`)),console.log();for(let s of n.bots){let a=s.status==="running"?E.default.green:s.status==="error"?E.default.red:E.default.yellow;if(console.log(` ${E.default.bold(s.botUsername)} ${a(`[${s.status}]`)}`),console.log(` ID: ${s.botId}`),console.log(` Uptime: ${cs(s.uptimeSeconds)}`),console.log(` Messages: ${s.messagesReceived} in / ${s.messagesSent} out`),s.chunkedMessages>0&&console.log(` Chunked: ${s.chunkedMessages} messages, ${s.totalChunksSent} chunks`),console.log(` Rooms: ${s.roomsActive} active`),console.log(` Errors: ${s.errors}`),s.lastError&&(console.log(` Last Error: ${E.default.red(s.lastError)}`),console.log(` Error At: ${s.lastErrorAt}`)),console.log(` Last Active: ${s.lastActivity??"N/A"}`),s.roomDetails&&s.roomDetails.length>0){console.log(E.default.dim(" Rooms:"));for(let c of s.roomDetails)console.log(E.default.dim(` ${c.roomName} \u2014 ${c.messagesInRoom} msgs, last: ${c.lastActivityInRoom??"N/A"}`))}console.log()}}console.log(E.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function cs(e){if(e<60)return`${e}s`;if(e<3600)return`${Math.floor(e/60)}m ${e%60}s`;let t=Math.floor(e/3600),o=Math.floor(e%3600/60);return t<24?`${t}h ${o}m`:`${Math.floor(t/24)}d ${t%24}h ${o}m`}var sn=require("commander"),Ve=u(require("chalk")),ms=u(require("ora"));M();ue();je();var qi=new sn.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{b()||(console.log(Ve.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,ms.default)("Restarting gateway...").start(),o=await Be();if(o.success){t.succeed(Ve.default.green(`Gateway restarted: ${o.message}`));try{await T(),console.log(Ve.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(Ve.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(Ve.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),ps=new sn.Command("gateway").description("Manage the OpenClaw gateway").addCommand(qi);var fe=require("commander"),k=u(require("chalk")),Re=u(require("ora")),ge=u(require("axios"));Gt();M();var Ie="http://localhost:7331",Vi=new fe.Command("start").description("Start a Claude Code session for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID (default: auto-generated)").option("--port <port>","MCP server port (default: 7332)","7332").option("--project <dir>","Project directory",process.cwd()).action(async e=>{b()||(console.log(k.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=e.sessionId||`session-${Date.now()}`,n=parseInt(e.port,10),r=e.project.replace(/^~/,process.env.HOME||""),s=(0,Re.default)("Starting Claude Code session...").start();try{await ge.default.post(`${Ie}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),s.text="Gateway toggled \u2014 launching MCP server...";let c=Uo({sessionId:o,port:n,projectDir:r}).pid||0;await new Promise(l=>setTimeout(l,1500)),s.text="MCP server running \u2014 launching Claude Code...",Fo({sessionId:o,port:n,projectDir:r}),Go(o,0,c,n,r),s.succeed(k.default.green("Claude Code session started")+k.default.dim(` (session: ${o}, port: ${n})`)),console.log(k.default.dim(` Bot: ${e.bot}`)),console.log(k.default.dim(` Room: ${e.room}`)),console.log(k.default.dim(` Project: ${r}`)),console.log(k.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let c=a.response?.data?.message||a.message||"Unknown error";s.fail(k.default.red(`Failed to start Claude Code: ${c}`)),process.exit(1)}}),Ki=new fe.Command("stop").description("Stop a Claude Code session").option("--bot <botId>","Bot ID or username").option("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID to stop").action(async e=>{b()||(console.log(k.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,Re.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await ge.default.post(`${Ie}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let n=e.sessionId;if(!n)try{let a=((await ge.default.get(`${Ie}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(c=>c.botId===e.bot&&c.roomId===e.room);a&&(n=a.sessionId)}catch{}n?(Wo(n),o.succeed(k.default.green(`Claude Code session stopped (${n})`))):(o.succeed(k.default.green("Claude Code toggled off at gateway")),console.log(k.default.dim(" No local session found to kill \u2014 may need to close Claude Code manually.")))}catch(n){let r=n.response?.data?.message||n.message||"Unknown error";o.fail(k.default.red(`Failed to stop Claude Code: ${r}`)),process.exit(1)}}),Yi=new fe.Command("status").description("Show active Claude Code sessions").action(async()=>{b()||(console.log(k.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,Re.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await ge.default.get(`${Ie}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let n=qo();if(t.stop(),o.length===0&&n.length===0){console.log(k.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(k.default.bold(`
161
168
  Gateway Claude Code Rooms:`)),console.log(k.default.dim(" Bot".padEnd(30)+"Room".padEnd(30)+"Session".padEnd(20)+"Enabled")),console.log(k.default.dim(" "+"-".repeat(88)));for(let r of o){let s=r.enabled?k.default.green("ON"):k.default.dim("OFF");console.log(` ${(r.botId||"").padEnd(30)}${(r.roomName||r.roomId||"").padEnd(30)}${(r.sessionId||"-").padEnd(20)}${s}`)}}if(n.length>0){console.log(k.default.bold(`
162
- Local Sessions:`)),console.log(k.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(k.default.dim(" "+"-".repeat(90)));for(let r of n)console.log(` ${r.sessionId.padEnd(25)}${String(r.port).padEnd(8)}${String(r.mcpPid).padEnd(10)}${r.projectDir.padEnd(40)}${r.startedAt}`)}console.log("")}catch(o){t.fail(k.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),Ei=new fe.Command("group").description("Group bots/rooms into a shared Claude Code session").requiredOption("--session <id>","Session ID to group under").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").action(async e=>{let t=(0,Ie.default)("Grouping bot+room into session...").start();try{await ge.default.post(`${Ce}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:e.session},{timeout:1e4}),t.succeed(k.default.green(`Grouped ${e.bot} + ${e.room} into session "${e.session}"`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(k.default.red(`Failed to group: ${n}`)),process.exit(1)}}),Pi=new fe.Command("allow").description("Add a user to the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to allow (e.g. @alice:server)").action(async e=>{let t=(0,Ie.default)("Adding user to allowlist...").start();try{await ge.default.post(`${Ce}/claude-code/allow`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(k.default.green(`Added ${e.user} to allowlist for ${e.bot} in ${e.room}`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(k.default.red(`Failed to add user: ${n}`)),process.exit(1)}}),Di=new fe.Command("revoke").description("Remove a user from the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to revoke").action(async e=>{let t=(0,Ie.default)("Removing user from allowlist...").start();try{await ge.default.post(`${Ce}/claude-code/revoke`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(k.default.green(`Removed ${e.user} from allowlist for ${e.bot} in ${e.room}`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(k.default.red(`Failed to revoke user: ${n}`)),process.exit(1)}}),ns=new fe.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(xi).addCommand(Ri).addCommand(Ai).addCommand(Ei).addCommand(Pi).addCommand(Di);Ae();async function Oi(){await Cn(process.argv);let e=new rs.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.3.1"),e.addCommand(hr),e.addCommand(br),e.addCommand(Sr),e.addCommand(Pr),e.addCommand(Fn),e.addCommand(Nr),e.addCommand(Xr),e.addCommand(Vo),e.addCommand(es),e.addCommand(os),e.addCommand(ns),e.parse(process.argv)}Oi().catch(e=>{console.error(e),process.exit(1)});
169
+ Local Sessions:`)),console.log(k.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(k.default.dim(" "+"-".repeat(90)));for(let r of n)console.log(` ${r.sessionId.padEnd(25)}${String(r.port).padEnd(8)}${String(r.mcpPid).padEnd(10)}${r.projectDir.padEnd(40)}${r.startedAt}`)}console.log("")}catch(o){t.fail(k.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),Ji=new fe.Command("group").description("Group bots/rooms into a shared Claude Code session").requiredOption("--session <id>","Session ID to group under").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").action(async e=>{let t=(0,Re.default)("Grouping bot+room into session...").start();try{await ge.default.post(`${Ie}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:e.session},{timeout:1e4}),t.succeed(k.default.green(`Grouped ${e.bot} + ${e.room} into session "${e.session}"`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(k.default.red(`Failed to group: ${n}`)),process.exit(1)}}),zi=new fe.Command("allow").description("Add a user to the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to allow (e.g. @alice:server)").action(async e=>{let t=(0,Re.default)("Adding user to allowlist...").start();try{await ge.default.post(`${Ie}/claude-code/allow`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(k.default.green(`Added ${e.user} to allowlist for ${e.bot} in ${e.room}`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(k.default.red(`Failed to add user: ${n}`)),process.exit(1)}}),Xi=new fe.Command("revoke").description("Remove a user from the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to revoke").action(async e=>{let t=(0,Re.default)("Removing user from allowlist...").start();try{await ge.default.post(`${Ie}/claude-code/revoke`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(k.default.green(`Removed ${e.user} from allowlist for ${e.bot} in ${e.room}`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(k.default.red(`Failed to revoke user: ${n}`)),process.exit(1)}}),gs=new fe.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(Vi).addCommand(Ki).addCommand(Yi).addCommand(Ji).addCommand(zi).addCommand(Xi);Ee();async function Qi(){await An(process.argv);let e=new fs.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.3.2"),e.addCommand(Sr),e.addCommand($r),e.addCommand(Ir),e.addCommand(Tr),e.addCommand(Kn),e.addCommand(jr),e.addCommand(ls),e.addCommand(Jo),e.addCommand(us),e.addCommand(ps),e.addCommand(gs),e.parse(process.argv)}Qi().catch(e=>{console.error(e),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "badgerclaw",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "engines": {
5
5
  "node": ">=18"
6
6
  },