badgerclaw 0.2.61 → 0.2.64

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 (3) hide show
  1. package/README.md +9 -0
  2. package/dist/index.js +54 -52
  3. package/package.json +4 -1
package/README.md CHANGED
@@ -4,10 +4,19 @@ One-click bot provisioning for BadgerClaw.
4
4
 
5
5
  ## Install
6
6
 
7
+ **Prerequisites:** Node.js **18+** and npm must already be installed (badgerclaw
8
+ is a Node CLI installed via npm). On a fresh/bare host, install Node first —
9
+ e.g. [nodesource](https://github.com/nodesource/distributions) on Linux or
10
+ [nvm](https://github.com/nvm-sh/nvm) (`nvm install 18`) — then:
11
+
7
12
  ```bash
8
13
  npm install -g badgerclaw
9
14
  ```
10
15
 
16
+ For the Hermes runtime, `badgerclaw setup --hermes` installs + starts Docker for
17
+ you (Docker Desktop/colima on macOS, docker.io on Linux), so you don't need to
18
+ install Docker yourself.
19
+
11
20
  ## Usage
12
21
 
13
22
  ```bash
package/dist/index.js CHANGED
@@ -1,20 +1,20 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Cr=Object.create;var tt=Object.defineProperty;var Ir=Object.getOwnPropertyDescriptor;var kr=Object.getOwnPropertyNames;var xr=Object.getPrototypeOf,Rr=Object.prototype.hasOwnProperty;var N=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ar=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Nt=(e,t)=>{for(var o in t)tt(e,o,{get:t[o],enumerable:!0})},Po=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of kr(t))!Rr.call(e,r)&&r!==o&&tt(e,r,{get:()=>t[r],enumerable:!(n=Ir(t,r))||n.enumerable});return e};var d=(e,t,o)=>(o=e!=null?Cr(xr(e)):{},Po(t||!e||!e.__esModule?tt(o,"default",{value:e,enumerable:!0}):o,e)),Oo=e=>Po(tt({},"__esModule",{value:!0}),e);function _(){try{let e=Oe.default.readFileSync(Mt,"utf-8");return JSON.parse(e)}catch{return null}}function ot(e){Oe.default.mkdirSync(No,{recursive:!0}),Oe.default.writeFileSync(Mt,JSON.stringify(e,null,2),{mode:384})}function De(){try{Oe.default.unlinkSync(Mt)}catch{}}function nt(){let e=_();return e?new Date(e.expires_at)>new Date:!1}function rt(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var Oe,Bt,Lo,No,Mt,j=N(()=>{"use strict";Oe=d(require("fs")),Bt=d(require("path")),Lo=d(require("os")),No=Bt.default.join(Lo.default.homedir(),".badgerclaw"),Mt=Bt.default.join(No,"auth.json")});function Ut(){return jo.default.createHash("sha256").update(`${K.default.hostname()}-${K.default.platform()}-${K.default.arch()}`).digest("hex").slice(0,16)}function q(){let e=_();if(e?.instance_id)return e.instance_id;let t=Ut();return`openclaw-${K.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function st(){return{hostname:K.default.hostname(),os:K.default.platform(),arch:K.default.arch(),uptimeSeconds:Math.floor(K.default.uptime()),memFreeMb:Math.floor(K.default.freemem()/1024/1024)}}var K,jo,$e=N(()=>{"use strict";K=d(require("os")),jo=d(require("crypto"));j()});var Bo,B,Mo,ne=N(()=>{"use strict";Bo=process.env.BADGERCLAW_ENV==="local",B=process.env.BADGERCLAW_API_URL??(Bo?"http://localhost:8000":"https://api.badger.signout.io"),Mo=process.env.BADGERCLAW_AUTH_URL??(Bo?"http://localhost:5500":"https://badgerclaw.ai")});function Fo(){return Te}function Er(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 Ft(){let e=_();if(!e?.refresh_token||!e?.email)return Te=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=Er(e.access_token);try{let o=await Le.default.post(`${it}/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 Te="server returned no access_token",null;let s=n.expires_in||3600,a=new Date(Date.now()+s*1e3).toISOString();return ot({...e,access_token:r,expires_at:a}),Te=null,r}catch(o){let n=o?.response?.status,r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";Te=n?`HTTP ${n}: ${r}`:`network error: ${r}`;let s=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(n===403&&Uo.test(s))throw De(),new ve(s);return null}}function Gt(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 Go(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(Uo.test(n))return De(),Promise.reject(new ve(n))}return Promise.reject(t)}),e}function Ho(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,at||(at=Ft().finally(()=>{at=null}));let n=await at;return n?(o.headers.Authorization=`Bearer ${n}`,e.request(o)):Promise.reject(t)}),e}function P(){let e=_(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=Le.default.create({baseURL:it,headers:t});return Gt(o),Ho(o),Go(o),o}function Vo(){return Gt(Le.default.create({baseURL:it,headers:{"Content-Type":"application/json"}}))}function Ne(e){let t=Le.default.create({baseURL:it,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return Gt(t),Ho(t),Go(t),t}var Le,it,ve,Uo,at,Te,ue=N(()=>{"use strict";Le=d(require("axios"));j();ne();it=B,ve=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},Uo=/account\s+has\s+been\s+(deleted|deactivated)/i,at=null,Te=null});function Jo(){try{let e=re.default.statSync(me);return Date.now()-e.mtimeMs>Ko}catch{return!0}}function Ht(){try{return re.default.mkdirSync(Vt.default.dirname(me),{recursive:!0}),re.default.writeFileSync(me,String(process.pid),{flag:"wx"}),!0}catch{if(Jo())try{return re.default.unlinkSync(me),re.default.writeFileSync(me,String(process.pid),{flag:"wx"}),!0}catch{return!1}return!1}}function Yo(){try{re.default.unlinkSync(me)}catch{}}async function zo(e){let t=!1;for(let o=0;o<Pr;o++){if(Ht()){t=!0;break}await new Promise(n=>setTimeout(n,qo))}t||console.warn("[config-lock] Could not acquire lock after timeout \u2014 proceeding without lock");try{return await e()}finally{t&&Yo()}}function pe(e){let t=Ht();if(!t&&Jo()){try{re.default.unlinkSync(me)}catch{}t=Ht()}try{return e()}finally{t&&Yo()}}var re,Wo,Vt,me,Ko,qo,Pr,je=N(()=>{"use strict";re=d(require("fs")),Wo=d(require("os")),Vt=d(require("path")),me=Vt.default.join(Wo.default.homedir(),".openclaw","openclaw.json.lock"),Ko=1e4,qo=50,Pr=Math.ceil(Ko/qo)});var ge=Ar((Ua,Or)=>{Or.exports={name:"badgerclaw",version:"0.2.61",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 lt(e=jr){try{return Kt.default.readdirSync(e,{withFileTypes:!0}).filter(t=>t.isDirectory()&&t.name.startsWith("badgerclaw-connect-")).map(t=>X.default.join(e,t.name))}catch{return[]}}function Br(){return[...lt().map(t=>X.default.join(t,"node_modules/@badgerclaw/connect/package.json")),X.default.join(Nr,"package.json"),X.default.join(Xo,"node_modules/@badgerclaw/connect/package.json"),X.default.join(Xo,"package.json")]}function qt(){return"0.2.61"}function dt(){for(let e of Br())try{let t=Kt.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 Mr(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function F(){if((0,Wt.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,Wt.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:Mr(t.stdout)||null}async function Ur(){let e=new AbortController,t=setTimeout(()=>e.abort(),Tr);try{let o=await fetch(Dr,{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 Fr(e){let t=[];if(e.cli&&e.cli!=="unknown"){let n=qt();n!==e.cli&&t.push({component:"cli",current:n,approved:e.cli})}if(!(F()!==null))return t;if(e.plugin&&e.plugin!=="unknown"){let n=dt();(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=F();(n===null||n!==e.supported_openclaw)&&t.push({component:"openclaw",current:n??"not installed",approved:e.supported_openclaw})}return t}function Gr(e){return e[2]}function Hr(e){return!e||e.startsWith("-")?!0:Lr.has(e)}function Vr(e){let t=[];t.push(""),t.push(se.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let n=o.component.padEnd(8);t.push(` ${n} ${se.default.yellow(o.current)} \u2192 ${se.default.green(o.approved)} ${se.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(se.default.green(" To fix, run:")),t.push(se.default.green.bold(" badgerclaw setup")),t.push(""),t.push(se.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
3
- `)}async function Qo(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=Gr(e);if(Hr(t))return;let o=await Ur();if(!o)return;let n=Fr(o);n.length!==0&&(process.stderr.write(Vr(n)),process.exit(1))}var Kt,ct,X,Wt,se,Dr,Tr,Lr,Xo,Nr,jr,Ce=N(()=>{"use strict";Kt=d(require("fs")),ct=d(require("os")),X=d(require("path")),Wt=require("child_process"),se=d(require("chalk"));ne();Dr=`${B}/api/v1/dashboard/versions/latest`,Tr=2500,Lr=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),Xo=X.default.join(ct.default.homedir(),".openclaw/extensions/badgerclaw"),Nr=X.default.join(ct.default.homedir(),".openclaw/npm/node_modules/@badgerclaw/connect"),jr=X.default.join(ct.default.homedir(),".openclaw/npm/projects")});var nn={};Nt(nn,{HERMES_IMAGE_DEFAULT:()=>Ie,detectCapabilities:()=>fe,detectDiskFreeGb:()=>on,detectDocker:()=>ut,detectHermes:()=>mt,detectOpenClaw:()=>tn});function ut(){if((0,Be.spawnSync)("which",["docker"],{encoding:"utf-8"}).status!==0)return{installed:!1};let t=(0,Be.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 tn(){let e=F();return e?{installed:!0,version:e}:{installed:!1}}function mt(e){if(!e.installed)return{installed:!1};let t=process.env.HERMES_IMAGE||Ie;return(0,Be.spawnSync)("docker",["image","inspect","--format","{{.RepoDigests}}",t],{encoding:"utf-8",timeout:3e3}).status!==0?{installed:!1}:{installed:!0,image:t}}function on(){let e=en.default.join(Jt.default.homedir(),".badgerclaw"),t=Zo.default.existsSync(e)?e:Jt.default.homedir();if(process.platform==="win32")return null;let o=(0,Be.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 fe(){let e=ut();return{openclaw:tn(),hermes:mt(e),docker:e,disk_free_gb:on(),ports_in_use:[]}}var Be,Zo,Jt,en,Ie,he=N(()=>{"use strict";Be=require("child_process"),Zo=d(require("fs")),Jt=d(require("os")),en=d(require("path"));Ce();Ie="hermes-agent-bc:bundled"});function gt(e){return J.default.join(Wr,`bot-${e}`)}function Xt(e){return`badgerclaw-hermes-bot-${e}`}function Qt(){if(!O.default.existsSync(Yt))return{hermes_bots:{}};try{let e=O.default.readFileSync(Yt,"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 qr(e){O.default.existsSync(pt)||O.default.mkdirSync(pt,{recursive:!0,mode:448}),O.default.writeFileSync(Yt,JSON.stringify(e,null,2)+`
5
- `,{mode:384})}function Jr(e,t=Kr){let o=new Set(Object.values(e.hermes_bots).map(r=>r.port)),n=t;for(;o.has(n)||!Yr(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 Yr(e){let t=an.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 ln(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 zr(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 Xr(e){switch(e){case"gemini":return"GOOGLE_API_KEY";case"anthropic":return"ANTHROPIC_API_KEY";case"openrouter":return"OPENROUTER_API_KEY"}}function Qr(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(`${Xr(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,sn.randomBytes)(24).toString("hex")}`),o.join(`
2
+ "use strict";var jr=Object.create;var at=Object.defineProperty;var Mr=Object.getOwnPropertyDescriptor;var Ur=Object.getOwnPropertyNames;var Hr=Object.getPrototypeOf,Fr=Object.prototype.hasOwnProperty;var j=(e,t)=>()=>(e&&(t=e(e=0)),t);var Gr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Wt=(e,t)=>{for(var o in t)at(e,o,{get:t[o],enumerable:!0})},Uo=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Ur(t))!Fr.call(e,r)&&r!==o&&at(e,r,{get:()=>t[r],enumerable:!(n=Mr(t,r))||n.enumerable});return e};var d=(e,t,o)=>(o=e!=null?jr(Hr(e)):{},Uo(t||!e||!e.__esModule?at(o,"default",{value:e,enumerable:!0}):o,e)),Ho=e=>Uo(at({},"__esModule",{value:!0}),e);function S(){try{let e=Be.default.readFileSync(Kt,"utf-8");return JSON.parse(e)}catch{return null}}function it(e){Be.default.mkdirSync(Vo,{recursive:!0}),Be.default.writeFileSync(Kt,JSON.stringify(e,null,2),{mode:384})}function je(){try{Be.default.unlinkSync(Kt)}catch{}}function ct(){let e=S();return e?new Date(e.expires_at)>new Date:!1}function lt(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var Be,qt,Wo,Vo,Kt,M=j(()=>{"use strict";Be=d(require("fs")),qt=d(require("path")),Wo=d(require("os")),Vo=qt.default.join(Wo.default.homedir(),".badgerclaw"),Kt=qt.default.join(Vo,"auth.json")});function Jt(){return qo.default.createHash("sha256").update(`${J.default.hostname()}-${J.default.platform()}-${J.default.arch()}`).digest("hex").slice(0,16)}function Y(){let e=S();if(e?.instance_id)return e.instance_id;let t=Jt();return`openclaw-${J.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function dt(){return{hostname:J.default.hostname(),os:J.default.platform(),arch:J.default.arch(),uptimeSeconds:Math.floor(J.default.uptime()),memFreeMb:Math.floor(J.default.freemem()/1024/1024)}}var J,qo,Ce=j(()=>{"use strict";J=d(require("os")),qo=d(require("crypto"));M()});var Ko,U,Jo,se=j(()=>{"use strict";Ko=process.env.BADGERCLAW_ENV==="local",U=process.env.BADGERCLAW_API_URL??(Ko?"http://localhost:8000":"https://api.badger.signout.io"),Jo=process.env.BADGERCLAW_AUTH_URL??(Ko?"http://localhost:5500":"https://badgerclaw.ai")});function zo(){return Me}function Wr(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 Yt(){let e=S();if(!e?.refresh_token||!e?.email)return Me=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=Wr(e.access_token);try{let o=await Ue.default.post(`${mt}/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 Me="server returned no access_token",null;let s=n.expires_in||3600,a=new Date(Date.now()+s*1e3).toISOString();return it({...e,access_token:r,expires_at:a}),Me=null,r}catch(o){let n=o?.response?.status,r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";Me=n?`HTTP ${n}: ${r}`:`network error: ${r}`;let s=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(n===403&&Yo.test(s))throw je(),new Ie(s);return null}}function zt(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 Xo(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(Yo.test(n))return je(),Promise.reject(new Ie(n))}return Promise.reject(t)}),e}function Qo(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,ut||(ut=Yt().finally(()=>{ut=null}));let n=await ut;return n?(o.headers.Authorization=`Bearer ${n}`,e.request(o)):Promise.reject(t)}),e}function O(){let e=S(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=Ue.default.create({baseURL:mt,headers:t});return zt(o),Qo(o),Xo(o),o}function Zo(){return zt(Ue.default.create({baseURL:mt,headers:{"Content-Type":"application/json"}}))}function He(e){let t=Ue.default.create({baseURL:mt,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return zt(t),Qo(t),Xo(t),t}var Ue,mt,Ie,Yo,ut,Me,fe=j(()=>{"use strict";Ue=d(require("axios"));M();se();mt=U,Ie=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},Yo=/account\s+has\s+been\s+(deleted|deactivated)/i,ut=null,Me=null});function nn(){try{let e=ae.default.statSync(he);return Date.now()-e.mtimeMs>tn}catch{return!0}}function Xt(){try{return ae.default.mkdirSync(Qt.default.dirname(he),{recursive:!0}),ae.default.writeFileSync(he,String(process.pid),{flag:"wx"}),!0}catch{if(nn())try{return ae.default.unlinkSync(he),ae.default.writeFileSync(he,String(process.pid),{flag:"wx"}),!0}catch{return!1}return!1}}function rn(){try{ae.default.unlinkSync(he)}catch{}}async function sn(e){let t=!1;for(let o=0;o<Vr;o++){if(Xt()){t=!0;break}await new Promise(n=>setTimeout(n,on))}t||console.warn("[config-lock] Could not acquire lock after timeout \u2014 proceeding without lock");try{return await e()}finally{t&&rn()}}function ye(e){let t=Xt();if(!t&&nn()){try{ae.default.unlinkSync(he)}catch{}t=Xt()}try{return e()}finally{t&&rn()}}var ae,en,Qt,he,tn,on,Vr,Fe=j(()=>{"use strict";ae=d(require("fs")),en=d(require("os")),Qt=d(require("path")),he=Qt.default.join(en.default.homedir(),".openclaw","openclaw.json.lock"),tn=1e4,on=50,Vr=Math.ceil(tn/on)});var we=Gr((ui,qr)=>{qr.exports={name:"badgerclaw",version:"0.2.64",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 gt(e=Xr){try{return eo.default.readdirSync(e,{withFileTypes:!0}).filter(t=>t.isDirectory()&&t.name.startsWith("badgerclaw-connect-")).map(t=>ee.default.join(e,t.name))}catch{return[]}}function Qr(){return[...gt().map(t=>ee.default.join(t,"node_modules/@badgerclaw/connect/package.json")),ee.default.join(zr,"package.json"),ee.default.join(an,"node_modules/@badgerclaw/connect/package.json"),ee.default.join(an,"package.json")]}function to(){return"0.2.64"}function ft(){for(let e of Qr())try{let t=eo.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 Zr(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function W(){if((0,Zt.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,Zt.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:Zr(t.stdout)||null}async function es(){let e=new AbortController,t=setTimeout(()=>e.abort(),Jr);try{let o=await fetch(Kr,{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 ts(e){let t=[];if(e.cli&&e.cli!=="unknown"){let n=to();n!==e.cli&&t.push({component:"cli",current:n,approved:e.cli})}if(!(W()!==null))return t;if(e.plugin&&e.plugin!=="unknown"){let n=ft();(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=W();(n===null||n!==e.supported_openclaw)&&t.push({component:"openclaw",current:n??"not installed",approved:e.supported_openclaw})}return t}function os(e){return e[2]}function ns(e){return!e||e.startsWith("-")?!0:Yr.has(e)}function rs(e){let t=[];t.push(""),t.push(ie.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let n=o.component.padEnd(8);t.push(` ${n} ${ie.default.yellow(o.current)} \u2192 ${ie.default.green(o.approved)} ${ie.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(ie.default.green(" To fix, run:")),t.push(ie.default.green.bold(" badgerclaw setup")),t.push(""),t.push(ie.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=os(e);if(ns(t))return;let o=await es();if(!o)return;let n=ts(o);n.length!==0&&(process.stderr.write(rs(n)),process.exit(1))}var eo,pt,ee,Zt,ie,Kr,Jr,Yr,an,zr,Xr,Re=j(()=>{"use strict";eo=d(require("fs")),pt=d(require("os")),ee=d(require("path")),Zt=require("child_process"),ie=d(require("chalk"));se();Kr=`${U}/api/v1/dashboard/versions/latest`,Jr=2500,Yr=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),an=ee.default.join(pt.default.homedir(),".openclaw/extensions/badgerclaw"),zr=ee.default.join(pt.default.homedir(),".openclaw/npm/node_modules/@badgerclaw/connect"),Xr=ee.default.join(pt.default.homedir(),".openclaw/npm/projects")});var pn={};Wt(pn,{HERMES_IMAGE_DEFAULT:()=>xe,detectCapabilities:()=>ce,detectDiskFreeGb:()=>mn,detectDocker:()=>ht,detectHermes:()=>yt,detectOpenClaw:()=>un});function ht(){if((0,Ge.spawnSync)("which",["docker"],{encoding:"utf-8"}).status!==0)return{installed:!1};let t=(0,Ge.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 un(){let e=W();return e?{installed:!0,version:e}:{installed:!1}}function yt(e){if(!e.installed)return{installed:!1};let t=process.env.HERMES_IMAGE||xe;return(0,Ge.spawnSync)("docker",["image","inspect","--format","{{.RepoDigests}}",t],{encoding:"utf-8",timeout:3e3}).status!==0?{installed:!1}:{installed:!0,image:t}}function mn(){let e=dn.default.join(oo.default.homedir(),".badgerclaw"),t=ln.default.existsSync(e)?e:oo.default.homedir();if(process.platform==="win32")return null;let o=(0,Ge.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=ht();return{openclaw:un(),hermes:yt(e),docker:e,disk_free_gb:mn(),ports_in_use:[]}}var Ge,ln,oo,dn,xe,be=j(()=>{"use strict";Ge=require("child_process"),ln=d(require("fs")),oo=d(require("os")),dn=d(require("path"));Re();xe="hermes-agent-bc:bundled"});function bt(e){return z.default.join(ss,`bot-${e}`)}function ro(e){return`badgerclaw-hermes-bot-${e}`}function so(){if(!N.default.existsSync(no))return{hermes_bots:{}};try{let e=N.default.readFileSync(no,"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 is(e){N.default.existsSync(wt)||N.default.mkdirSync(wt,{recursive:!0,mode:448}),N.default.writeFileSync(no,JSON.stringify(e,null,2)+`
5
+ `,{mode:384})}function cs(e,t=as){let o=new Set(Object.values(e.hermes_bots).map(r=>r.port)),n=t;for(;o.has(n)||!ls(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 ls(e){let t=hn.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 wn(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 us(e){switch(e){case"gemini":return"GOOGLE_API_KEY";case"anthropic":return"ANTHROPIC_API_KEY";case"openrouter":return"OPENROUTER_API_KEY"}}function ms(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(`${us(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,fn.randomBytes)(24).toString("hex")}`),o.join(`
6
6
  `)+`
7
- `}function Zr(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: ${zr(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 es(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 ts(e,t){let o=gt(e.botId);O.default.mkdirSync(o,{recursive:!0,mode:448});let n=J.default.join(o,".env"),r=J.default.join(o,"config.yaml"),s=J.default.join(o,"SOUL.md");return O.default.writeFileSync(n,Qr(e,t),{mode:384}),O.default.writeFileSync(r,Zr(e),{mode:384}),O.default.existsSync(s)||O.default.writeFileSync(s,es(e),{mode:384}),{dataDir:o,envPath:n,configPath:r,soulPath:s}}function os(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 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 dn(e,t={}){let o=t.docker??zt,n=e.image||process.env.HERMES_IMAGE||Ie;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=Qt(),s=r.hermes_bots[e.botId],a=s?.port??Jr(r,t.portBase),l=s?.container_name??Xt(e.botId);if(ts(e,a),!t.skipDocker){o.run(["rm","-f",l]);let i=os({containerName:l,dataDir:gt(e.botId),port:a,image:n}),u=o.run(i);if(u.status!==0)throw new Error(`docker run failed (exit ${u.status}): ${u.stderr||u.stdout}`)}let c={bot_id:e.botId,runtime:"hermes",container_name:l,port:a,data_dir:gt(e.botId),image:n,started_at:new Date().toISOString()};return r.hermes_bots[e.botId]=c,qr(r),c}function un(e={}){let t=e.docker??zt,o=Qt(),n=[];for(let[r,s]of Object.entries(o.hermes_bots)){let a=t.run(["inspect","--format","{{.State.Status}}",s.container_name]),l,c=a.stdout.trim()||null;a.status!==0?(l="missing",c=(a.stderr||a.stdout).trim()||null):c==="running"?l="running":c==="exited"||c==="dead"||c==="created"?l="stopped":l="unknown",n.push({bot_id:r,container_name:s.container_name,status:l,raw:c})}return n}function rs(e){let t=e.match(ns);return t?t[1].trim():null}async function Zt(e,t,o,n={}){let r={recoveryKey:null,posted:!1,envUpdated:!1};if(!e.backendBotId)return r;let a=(n.docker??zt).run(["logs",t]),l=`${a.stdout}
10
- ${a.stderr}`,c=rs(l);if(!c)return r;if(r.recoveryKey=c,n.api)try{let u=await n.api.post(`/api/v1/hermes/bots/${e.backendBotId}/runtime-bootstrap`,{recovery_key:c,image_ref:o});r.posted=u.status>=200&&u.status<300}catch(u){console.warn(`[hermes] failed to POST recovery key for ${e.botId}: ${u.message}. Daemon will retry next beat.`)}let i=n.envPath??J.default.join(gt(e.botId),".env");return O.default.existsSync(i)&&(O.default.readFileSync(i,"utf-8").includes("MATRIX_RECOVERY_KEY=")||(O.default.appendFileSync(i,`
7
+ `}function ps(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 gs(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 fs(e,t){let o=bt(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,ms(e,t),{mode:384}),N.default.writeFileSync(r,ps(e),{mode:384}),N.default.existsSync(s)||N.default.writeFileSync(s,gs(e),{mode:384}),{dataDir:o,envPath:n,configPath:r,soulPath:s}}function St(e){let t=e.run(["network","inspect","bridge","--format","{{range .IPAM.Config}}{{.Subnet}} {{end}}"]);return t.status===0&&!!(t.stdout||"").trim()}function ao(e={}){let t=e.env??process.env;return t.BADGERCLAW_HERMES_NETWORK==="host"?!0:t.BADGERCLAW_HERMES_NETWORK==="bridge"?!1:!(e.bridgeUsable??(()=>St(_t)))()}function hs(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 bn(e,t={}){let o=t.docker??_t,n=e.image||process.env.HERMES_IMAGE||xe;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=so(),s=r.hermes_bots[e.botId],a=s?.port??cs(r,t.portBase),l=s?.container_name??ro(e.botId);if(fs(e,a),!t.skipDocker){o.run(["rm","-f",l]);let i=ao({bridgeUsable:()=>St(o)}),m=hs({containerName:l,dataDir:bt(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 c={bot_id:e.botId,runtime:"hermes",container_name:l,port:a,data_dir:bt(e.botId),image:n,started_at:new Date().toISOString()};return r.hermes_bots[e.botId]=c,is(r),c}function _n(e={}){let t=e.docker??_t,o=so(),n=[];for(let[r,s]of Object.entries(o.hermes_bots)){let a=t.run(["inspect","--format","{{.State.Status}}",s.container_name]),l,c=a.stdout.trim()||null;a.status!==0?(l="missing",c=(a.stderr||a.stdout).trim()||null):c==="running"?l="running":c==="exited"||c==="dead"||c==="created"?l="stopped":l="unknown",n.push({bot_id:r,container_name:s.container_name,status:l,raw:c})}return n}function ws(e){let t=e.match(ys);return t?t[1].trim():null}async function io(e,t,o,n={}){let r={recoveryKey:null,posted:!1,envUpdated:!1};if(!e.backendBotId)return r;let a=(n.docker??_t).run(["logs",t]),l=`${a.stdout}
10
+ ${a.stderr}`,c=ws(l);if(!c)return r;if(r.recoveryKey=c,n.api)try{let m=await n.api.post(`/api/v1/hermes/bots/${e.backendBotId}/runtime-bootstrap`,{recovery_key:c,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??z.default.join(bt(e.botId),".env");return N.default.existsSync(i)&&(N.default.readFileSync(i,"utf-8").includes("MATRIX_RECOVERY_KEY=")||(N.default.appendFileSync(i,`
11
11
  # Cross-signing recovery key captured from first-boot logs.
12
12
  # Hermes re-uses this on restart to re-sign the device after
13
13
  # Synapse rotates server keys.
14
14
  MATRIX_RECOVERY_KEY=${c}
15
- `),r.envUpdated=!0)),r}async function mn(e={}){let t=Qt(),o=[];for(let[n,r]of Object.entries(t.hermes_bots)){let s=J.default.join(r.data_dir,".env"),a=!1;try{O.default.existsSync(s)&&(a=O.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 l=await Zt({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:l.recoveryKey!==null,posted:l.posted,envUpdated:l.envUpdated})}catch(l){console.warn(`[hermes] recovery-key retry failed for ${n}: ${l.message}`),o.push({bot_id:n,attempted:!0,recoveryKeyFound:!1,posted:!1,envUpdated:!1})}}return o}var rn,sn,O,an,cn,J,pt,Wr,Yt,Kr,zt,ns,eo=N(()=>{"use strict";rn=require("child_process"),sn=require("crypto"),O=d(require("fs")),an=d(require("net")),cn=d(require("os")),J=d(require("path"));he();pt=J.default.join(cn.default.homedir(),".badgerclaw"),Wr=J.default.join(pt,"hermes"),Yt=J.default.join(pt,"state.json"),Kr=8642,zt={run:e=>{let t=(0,rn.spawnSync)("docker",e,{encoding:"utf-8"});return{status:t.status,stdout:t.stdout||"",stderr:t.stderr||""}}};ns=/SAVE THIS RECOVERY KEY[\s\S]*?key rotation:\s+((?:[A-Za-z0-9]{4}\s+){7,}[A-Za-z0-9]{4})/});function ft(e){return`'${e.replace(/'/g,"'\\''")}'`}function ss(){if(ae!==null)return ae;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(Me.default.existsSync(t))return ae=`${ft(process.execPath)} ${ft(t)}`,ae;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=no.default.join(o,"openclaw","openclaw.mjs");if(Me.default.existsSync(n))return ae=`${ft(process.execPath)} ${ft(n)}`,ae}}catch{}return ae="openclaw",ae}function to(e,t,o){t?t.fail(G.default.red(o)):e&&console.error(`[autopair] ${o}`)}async function as(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:ln()},n=dn(o);if(o.backendBotId){let r=_();if(r){let s=Ne(r.access_token);try{await Zt(o,Xt(o.botId),n.image,{api:{post:async(a,l)=>{let c=await s.post(a,l);return{status:c.status,data:c.data}}}})}catch(a){console.warn(`[hermes] recovery key capture failed for ${o.botId}: ${a.message}. Daemon will retry next beat.`)}}}}async function Ue(e,t,o,n){let r=_();if(!r)return;let s=n?null:(0,oo.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${B}/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(G.default.dim(`${t} already paired (race-loss; another channel redeemed first).`));return}let u=await a.json().catch(()=>({errors:[a.statusText]}));to(n,s,`Failed to redeem ${t}: ${u.errors?.[0]||a.status}`);return}let l=await a.json(),c=l.result??l;if((c.runtime??"openclaw")==="hermes"){try{await as(c),s?.succeed(G.default.green(`\u2705 ${c.bot_name} (${c.user_id}) running on Hermes \u2014 bot is live!`))}catch(u){to(n,s,`Failed to start Hermes container for ${t}: ${u.message}`)}return}await zo(async()=>{let u=c.user_id.split(":")[0].replace("@","").replace(/_bot$/,""),p;try{p=JSON.parse(Me.default.readFileSync(pn,"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:c.user_id,accessToken:c.access_token,homeserver:c.homeserver,encryption:!0,groupPolicy:"open",allowlistOnly:!1,dm:{policy:"open"}};c.device_id&&(E.deviceId=c.device_id),p.channels.badgerclaw.accounts[u]=E,Me.default.writeFileSync(pn,JSON.stringify(p,null,2),{mode:384})}),await fetch(`${B}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${r.access_token}`}}).catch(()=>{}),s?.succeed(G.default.green(`\u2705 ${c.bot_name} (${c.user_id}) paired \u2014 bot is live!`))}catch(a){to(n,s,`Failed to pair ${t}: ${a.message}`)}}async function Fe(e=!1){let t=_();if(!t)return 0;let o=Ne(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 l=e?null:(0,oo.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await Ue(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(c){l?.fail(G.default.red(`Error pairing ${a.bot_name}: ${c}`))}}if(s>0)try{let{execSync:a}=await import("child_process");a(`${ss()} gateway restart`,{stdio:"ignore"}),e||console.log(G.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(G.default.yellow(`
17
- \u26A1 ${s} bot(s) paired. Run: openclaw gateway restart`))}return s}catch{return 0}}var gn,G,oo,fn,no,Me,pn,ae,hn,Ge=N(()=>{"use strict";gn=require("commander"),G=d(require("chalk")),oo=d(require("ora")),fn=d(require("os")),no=d(require("path")),Me=d(require("fs"));j();ue();ne();$e();je();eo();pn=no.default.join(fn.default.homedir(),".openclaw","openclaw.json");ae=null;hn=new gn.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!_()){console.log(G.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(G.default.dim("Checking for pending bot pairs...")),await Fe(!1)===0&&console.log(G.default.dim("No pending pairs found."))})});async function io(){try{return await bt.default.get(ys,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function Ke(){try{let t=(await bt.default.get(`${Cn}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(ao=t.pluginVersion),t}catch{return{status:await io()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:ao,bots:[]}}}function co(e){e&&e!=="unknown"&&(ao=e)}async function ke(){try{return{success:!0,message:(await bt.default.post(`${Cn}/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 bt,fs,Cn,hs,ys,ao,ie=N(()=>{"use strict";bt=d(require("axios")),fs=7331,Cn=`http://localhost:${fs}`,hs=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,ys=`http://127.0.0.1:${hs}`,ao="unknown"});var Io={};Nt(Io,{getActiveSessions:()=>Co,launchClaudeCode:()=>So,launchMCPServer:()=>_o,recordSession:()=>$o,stopSession:()=>vo});function ho(){try{if(T.default.existsSync(fo))return JSON.parse(T.default.readFileSync(fo,"utf-8"))}catch{}return[]}function yo(e){T.default.mkdirSync(we,{recursive:!0}),T.default.writeFileSync(fo,JSON.stringify(e,null,2))}function Rt(e){try{return process.kill(e,0),!0}catch{return!1}}function Ps(){if(process.env.TMUX)return"tmux";try{if((0,Z.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),T.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function wo(e,t){let o=U.default.join(we,`claude-launcher-${t}.exp`),n=U.default.join(we,`pending-input-${t}.txt`);T.default.writeFileSync(n,"","utf-8");let r=`#!/usr/bin/expect -f
15
+ `),r.envUpdated=!0)),r}async function Sn(e={}){let t=so(),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 l=await io({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:l.recoveryKey!==null,posted:l.posted,envUpdated:l.envUpdated})}catch(l){console.warn(`[hermes] recovery-key retry failed for ${n}: ${l.message}`),o.push({bot_id:n,attempted:!0,recoveryKeyFound:!1,posted:!1,envUpdated:!1})}}return o}var gn,fn,N,hn,yn,z,wt,ss,no,as,_t,ys,kt=j(()=>{"use strict";gn=require("child_process"),fn=require("crypto"),N=d(require("fs")),hn=d(require("net")),yn=d(require("os")),z=d(require("path"));be();wt=z.default.join(yn.default.homedir(),".badgerclaw"),ss=z.default.join(wt,"hermes"),no=z.default.join(wt,"state.json"),as=8642,_t={run:e=>{let t=(0,gn.spawnSync)("docker",e,{encoding:"utf-8"});return{status:t.status,stdout:t.stdout||"",stderr:t.stderr||""}}};ys=/SAVE THIS RECOVERY KEY[\s\S]*?key rotation:\s+((?:[A-Za-z0-9]{4}\s+){7,}[A-Za-z0-9]{4})/});function vt(e){return`'${e.replace(/'/g,"'\\''")}'`}function bs(){if(le!==null)return le;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(We.default.existsSync(t))return le=`${vt(process.execPath)} ${vt(t)}`,le;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=uo.default.join(o,"openclaw","openclaw.mjs");if(We.default.existsSync(n))return le=`${vt(process.execPath)} ${vt(n)}`,le}}catch{}return le="openclaw",le}function co(e,t,o){t?t.fail(V.default.red(o)):e&&console.error(`[autopair] ${o}`)}async function _s(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:wn()},n=bn(o);if(o.backendBotId){let r=S();if(r){let s=He(r.access_token);try{await io(o,ro(o.botId),n.image,{api:{post:async(a,l)=>{let c=await s.post(a,l);return{status:c.status,data:c.data}}}})}catch(a){console.warn(`[hermes] recovery key capture failed for ${o.botId}: ${a.message}. Daemon will retry next beat.`)}}}}async function Ve(e,t,o,n){let r=S();if(!r)return;let s=n?null:(0,lo.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${U}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e,instance_id:Y()})});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]}));co(n,s,`Failed to redeem ${t}: ${m.errors?.[0]||a.status}`);return}let l=await a.json(),c=l.result??l;if((c.runtime??"openclaw")==="hermes"){try{await _s(c),s?.succeed(V.default.green(`\u2705 ${c.bot_name} (${c.user_id}) running on Hermes \u2014 bot is live!`))}catch(m){co(n,s,`Failed to start Hermes container for ${t}: ${m.message}`)}return}await sn(async()=>{let m=c.user_id.split(":")[0].replace("@","").replace(/_bot$/,""),p;try{p=JSON.parse(We.default.readFileSync(kn,"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:c.user_id,accessToken:c.access_token,homeserver:c.homeserver,encryption:!0,groupPolicy:"open",allowlistOnly:!1,dm:{policy:"open"}};c.device_id&&(P.deviceId=c.device_id),p.channels.badgerclaw.accounts[m]=P,We.default.writeFileSync(kn,JSON.stringify(p,null,2),{mode:384})}),await fetch(`${U}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${r.access_token}`}}).catch(()=>{}),s?.succeed(V.default.green(`\u2705 ${c.bot_name} (${c.user_id}) paired \u2014 bot is live!`))}catch(a){co(n,s,`Failed to pair ${t}: ${a.message}`)}}async function qe(e=!1){let t=S();if(!t)return 0;let o=He(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 l=e?null:(0,lo.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await Ve(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(c){l?.fail(V.default.red(`Error pairing ${a.bot_name}: ${c}`))}}if(s>0)try{let{execSync:a}=await import("child_process");a(`${bs()} 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 vn,V,lo,$n,uo,We,kn,le,Cn,Ke=j(()=>{"use strict";vn=require("commander"),V=d(require("chalk")),lo=d(require("ora")),$n=d(require("os")),uo=d(require("path")),We=d(require("fs"));M();fe();se();Ce();Fe();kt();kn=uo.default.join($n.default.homedir(),".openclaw","openclaw.json");le=null;Cn=new vn.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!S()){console.log(V.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(V.default.dim("Checking for pending bot pairs...")),await qe(!1)===0&&console.log(V.default.dim("No pending pairs found."))})});async function fo(){try{return await Rt.default.get(Ps,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function Xe(){try{let t=(await Rt.default.get(`${On}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(go=t.pluginVersion),t}catch{return{status:await fo()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:go,bots:[]}}}function ho(e){e&&e!=="unknown"&&(go=e)}async function Ae(){try{return{success:!0,message:(await Rt.default.post(`${On}/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 Rt,As,On,Es,Ps,go,de=j(()=>{"use strict";Rt=d(require("axios")),As=7331,On=`http://localhost:${As}`,Es=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,Ps=`http://127.0.0.1:${Es}`,go="unknown"});var Do={};Wt(Do,{getActiveSessions:()=>Po,launchClaudeCode:()=>xo,launchMCPServer:()=>Ro,recordSession:()=>Ao,stopSession:()=>Eo});function vo(){try{if(L.default.existsSync(ko))return JSON.parse(L.default.readFileSync(ko,"utf-8"))}catch{}return[]}function $o(e){L.default.mkdirSync(Se,{recursive:!0}),L.default.writeFileSync(ko,JSON.stringify(e,null,2))}function Lt(e){try{return process.kill(e,0),!0}catch{return!1}}function Vs(){if(process.env.TMUX)return"tmux";try{if((0,oe.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),L.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function Co(e,t){let o=G.default.join(Se,`claude-launcher-${t}.exp`),n=G.default.join(Se,`pending-input-${t}.txt`);L.default.writeFileSync(n,"","utf-8");let r=`#!/usr/bin/expect -f
18
18
  set timeout -1
19
19
  set msgfile "${n}"
20
20
 
@@ -51,21 +51,21 @@ send "\\r"
51
51
  interact timeout 2 {
52
52
  check_and_send_messages
53
53
  }
54
- `;return T.default.mkdirSync(we,{recursive:!0}),T.default.writeFileSync(o,r,{mode:493}),o}function bo(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function Os(e,t,o){let n=wo(e,o.BADGERCLAW_SESSION_ID||"default"),r=bo(o),s=`
54
+ `;return L.default.mkdirSync(Se,{recursive:!0}),L.default.writeFileSync(o,r,{mode:493}),o}function Io(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function qs(e,t,o){let n=Co(e,o.BADGERCLAW_SESSION_ID||"default"),r=Io(o),s=`
55
55
  tell application "iTerm"
56
56
  activate
57
57
  set newWindow to (create window with default profile)
58
58
  tell current session of newWindow
59
- write text "cd ${At(t)} && ${r} && ${At(n)}"
59
+ write text "cd ${Bt(t)} && ${r} && ${Bt(n)}"
60
60
  end tell
61
61
  end tell
62
- `;(0,Z.execSync)(`osascript -e '${s.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Ds(e,t,o){let n=wo(e,o.BADGERCLAW_SESSION_ID||"default"),r=bo(o),a=`
62
+ `;(0,oe.execSync)(`osascript -e '${s.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Ks(e,t,o){let n=Co(e,o.BADGERCLAW_SESSION_ID||"default"),r=Io(o),a=`
63
63
  tell application "Terminal"
64
64
  activate
65
- do script "${`cd ${At(t)} && ${r} && ${At(n)}`.replace(/"/g,'\\"')}"
65
+ do script "${`cd ${Bt(t)} && ${r} && ${Bt(n)}`.replace(/"/g,'\\"')}"
66
66
  end tell
67
- `;(0,Z.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Ts(e,t,o){let n=wo(e,o.BADGERCLAW_SESSION_ID||"default"),r=bo(o),s=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${r} && ${n}`;(0,Z.execSync)(`tmux new-session -d -s ${s} "${a}"`,{stdio:"pipe",timeout:1e4})}function At(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function _o(e){let t=U.default.join(__dirname,"..","claude-code","mcp-server.js"),o=T.default.existsSync(t)?t:U.default.join(__dirname,"mcp-server.js"),n=(0,Z.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 So(e){let t=U.default.join(U.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=U.default.join(__dirname,"..","claude-code","mcp-server.js"),n=U.default.join(__dirname,"mcp-server.js"),r=T.default.existsSync(t)?t:T.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}}}),l=U.default.join(we,`mcp-config-${e.sessionId}.json`);T.default.mkdirSync(we,{recursive:!0}),T.default.writeFileSync(l,a,"utf-8");let c=`claude --dangerously-skip-permissions --mcp-config ${l}`;switch(Ps()){case"iterm2":Os(c,e.projectDir,s);break;case"terminal":Ds(c,e.projectDir,s);break;case"tmux":Ts(c,e.projectDir,s);break;case"direct":(0,Z.spawn)(c,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...s},stdio:"ignore",detached:!0}).unref();break}}function $o(e,t,o,n,r){let s=ho().filter(a=>a.sessionId!==e);s.push({sessionId:e,pid:t,mcpPid:o,port:n,projectDir:r,startedAt:new Date().toISOString()}),yo(s)}function vo(e){let t=ho(),o=t.find(r=>r.sessionId===e);if(!o)return!1;if(o.mcpPid&&Rt(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&Rt(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,Z.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let n=t.filter(r=>r.sessionId!==e);return yo(n),!0}function Co(){let e=ho(),t=e.filter(o=>Rt(o.mcpPid)||Rt(o.pid));return t.length!==e.length&&yo(t),t}var Z,T,U,Kn,we,fo,Et=N(()=>{"use strict";Z=require("child_process"),T=d(require("fs")),U=d(require("path")),Kn=d(require("os")),we=U.default.join(Kn.default.homedir(),".badgerclaw"),fo=U.default.join(we,"claude-sessions.json")});async function ee(e){return e.command_type==="update_cli"?Ns(e.payload?.target_version):e.command_type==="update_plugin"?js(e.payload?.target_version):e.command_type==="restart_gateway"?Ls():e.command_type==="leave_room"?Xs(e.payload):e.command_type==="start_claude_code"?Gs(e.payload):e.command_type==="stop_claude_code"?Hs(e.payload):e.command_type==="start_claude_control"?Vs(e.payload):e.command_type==="stop_claude_control"?Ws(e.payload):e.command_type==="update_claude_tools"?Ks(e.payload):e.command_type==="bot_share_notify"?qs(e.payload):e.command_type==="bot_share_revoked"?Js(e.payload):e.command_type==="bot_share_expired"?Ys(e.payload):e.command_type==="bot_refresh"?zs(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function Ls(){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 Ns(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 Ms(),{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 js(e){let t=S.default.join(be.default.homedir(),".openclaw","extensions","badgerclaw"),o=S.default.join(be.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 u=S.default.dirname(S.default.dirname(S.default.dirname(o)));(0,A.execSync)(`npm install ${r}`,{cwd:u,stdio:"pipe",timeout:12e4});let p=S.default.join(o,"package.json"),E="unknown";h.default.existsSync(p)&&(E=JSON.parse(h.default.readFileSync(p,"utf-8")).version||"unknown"),co(E);try{(0,A.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await qn(E)}let s=t;(0,A.execSync)(`npm install ${r}`,{cwd:s,stdio:"pipe",timeout:12e4});let a=S.default.join(s,"node_modules","@badgerclaw","connect"),l=S.default.join(a,"package.json"),c="unknown";h.default.existsSync(l)&&(c=JSON.parse(h.default.readFileSync(l,"utf-8")).version||"unknown"),co(c),Bs(a,s);let i=S.default.join(s,"package.json");if(h.default.existsSync(i)&&h.default.existsSync(l))try{let u=JSON.parse(h.default.readFileSync(i,"utf-8")),p=JSON.parse(h.default.readFileSync(l,"utf-8"));u.version=c,p.openclaw&&(u.openclaw={...u.openclaw,...p.openclaw}),h.default.writeFileSync(i,JSON.stringify(u,null,2)+`
68
- `)}catch{}try{(0,A.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await qn(c)}catch(s){return{success:!1,message:`Plugin update failed: ${(s.stderr?.toString()||s.message||"").slice(0,500)}`}}}async function qn(e){for(let t=0;t<15;t++){await new Promise(o=>setTimeout(o,1e3));try{let o=await L.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 Bs(e,t){let o=S.default.join(e,"dist"),n=S.default.join(t,"dist");h.default.existsSync(o)&&(h.default.mkdirSync(n,{recursive:!0}),ko(o,n));let r=S.default.join(e,"openclaw.plugin.json");h.default.existsSync(r)&&h.default.copyFileSync(r,S.default.join(t,"openclaw.plugin.json"));let s=S.default.join(e,"scripts"),a=S.default.join(t,"scripts");h.default.existsSync(s)&&(h.default.mkdirSync(a,{recursive:!0}),ko(s,a));for(let l of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let c=S.default.join(t,l);h.default.existsSync(c)&&(h.default.statSync(c).isDirectory()?h.default.rmSync(c,{recursive:!0,force:!0}):h.default.unlinkSync(c))}}function ko(e,t){for(let o of h.default.readdirSync(e,{withFileTypes:!0})){let n=S.default.join(e,o.name),r=S.default.join(t,o.name);o.isDirectory()?(h.default.mkdirSync(r,{recursive:!0}),ko(n,r)):h.default.copyFileSync(n,r)}}function Ms(){try{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)("which badgerclaw",{stdio:"pipe"}).toString().trim();(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 Us(){let e=S.default.join(be.default.homedir(),".badgerclaw","workspace");h.default.mkdirSync(e,{recursive:!0});let t=S.default.join(e,".git");return h.default.existsSync(t)||(0,A.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),h.default.writeFileSync(S.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
67
+ `;(0,oe.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Js(e,t,o){let n=Co(e,o.BADGERCLAW_SESSION_ID||"default"),r=Io(o),s=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${r} && ${n}`;(0,oe.execSync)(`tmux new-session -d -s ${s} "${a}"`,{stdio:"pipe",timeout:1e4})}function Bt(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Ro(e){let t=G.default.join(__dirname,"..","claude-code","mcp-server.js"),o=L.default.existsSync(t)?t:G.default.join(__dirname,"mcp-server.js"),n=(0,oe.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 xo(e){let t=G.default.join(G.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=G.default.join(__dirname,"..","claude-code","mcp-server.js"),n=G.default.join(__dirname,"mcp-server.js"),r=L.default.existsSync(t)?t:L.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}}}),l=G.default.join(Se,`mcp-config-${e.sessionId}.json`);L.default.mkdirSync(Se,{recursive:!0}),L.default.writeFileSync(l,a,"utf-8");let c=`claude --dangerously-skip-permissions --mcp-config ${l}`;switch(Vs()){case"iterm2":qs(c,e.projectDir,s);break;case"terminal":Ks(c,e.projectDir,s);break;case"tmux":Js(c,e.projectDir,s);break;case"direct":(0,oe.spawn)(c,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...s},stdio:"ignore",detached:!0}).unref();break}}function Ao(e,t,o,n,r){let s=vo().filter(a=>a.sessionId!==e);s.push({sessionId:e,pid:t,mcpPid:o,port:n,projectDir:r,startedAt:new Date().toISOString()}),$o(s)}function Eo(e){let t=vo(),o=t.find(r=>r.sessionId===e);if(!o)return!1;if(o.mcpPid&&Lt(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&Lt(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,oe.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let n=t.filter(r=>r.sessionId!==e);return $o(n),!0}function Po(){let e=vo(),t=e.filter(o=>Lt(o.mcpPid)||Lt(o.pid));return t.length!==e.length&&$o(t),t}var oe,L,G,tr,Se,ko,jt=j(()=>{"use strict";oe=require("child_process"),L=d(require("fs")),G=d(require("path")),tr=d(require("os")),Se=G.default.join(tr.default.homedir(),".badgerclaw"),ko=G.default.join(Se,"claude-sessions.json")});async function ne(e){return e.command_type==="update_cli"?zs(e.payload?.target_version):e.command_type==="update_plugin"?Xs(e.payload?.target_version):e.command_type==="restart_gateway"?Ys():e.command_type==="leave_room"?ua(e.payload):e.command_type==="start_claude_code"?oa(e.payload):e.command_type==="stop_claude_code"?na(e.payload):e.command_type==="start_claude_control"?ra(e.payload):e.command_type==="stop_claude_control"?sa(e.payload):e.command_type==="update_claude_tools"?aa(e.payload):e.command_type==="bot_share_notify"?ia(e.payload):e.command_type==="bot_share_revoked"?ca(e.payload):e.command_type==="bot_share_expired"?la(e.payload):e.command_type==="bot_refresh"?da(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function Ys(){try{return(0,E.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,E.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 zs(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,E.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,E.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),r=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return Zs(),{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 Xs(e){let t=k.default.join(ke.default.homedir(),".openclaw","extensions","badgerclaw"),o=k.default.join(ke.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=k.default.dirname(k.default.dirname(k.default.dirname(o)));(0,E.execSync)(`npm install ${r}`,{cwd:m,stdio:"pipe",timeout:12e4});let p=k.default.join(o,"package.json"),P="unknown";h.default.existsSync(p)&&(P=JSON.parse(h.default.readFileSync(p,"utf-8")).version||"unknown"),ho(P);try{(0,E.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await or(P)}let s=t;(0,E.execSync)(`npm install ${r}`,{cwd:s,stdio:"pipe",timeout:12e4});let a=k.default.join(s,"node_modules","@badgerclaw","connect"),l=k.default.join(a,"package.json"),c="unknown";h.default.existsSync(l)&&(c=JSON.parse(h.default.readFileSync(l,"utf-8")).version||"unknown"),ho(c),Qs(a,s);let i=k.default.join(s,"package.json");if(h.default.existsSync(i)&&h.default.existsSync(l))try{let m=JSON.parse(h.default.readFileSync(i,"utf-8")),p=JSON.parse(h.default.readFileSync(l,"utf-8"));m.version=c,p.openclaw&&(m.openclaw={...m.openclaw,...p.openclaw}),h.default.writeFileSync(i,JSON.stringify(m,null,2)+`
68
+ `)}catch{}try{(0,E.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await or(c)}catch(s){return{success:!1,message:`Plugin update failed: ${(s.stderr?.toString()||s.message||"").slice(0,500)}`}}}async function or(e){for(let t=0;t<15;t++){await new Promise(o=>setTimeout(o,1e3));try{let o=await B.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 Qs(e,t){let o=k.default.join(e,"dist"),n=k.default.join(t,"dist");h.default.existsSync(o)&&(h.default.mkdirSync(n,{recursive:!0}),Oo(o,n));let r=k.default.join(e,"openclaw.plugin.json");h.default.existsSync(r)&&h.default.copyFileSync(r,k.default.join(t,"openclaw.plugin.json"));let s=k.default.join(e,"scripts"),a=k.default.join(t,"scripts");h.default.existsSync(s)&&(h.default.mkdirSync(a,{recursive:!0}),Oo(s,a));for(let l of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let c=k.default.join(t,l);h.default.existsSync(c)&&(h.default.statSync(c).isDirectory()?h.default.rmSync(c,{recursive:!0,force:!0}):h.default.unlinkSync(c))}}function Oo(e,t){for(let o of h.default.readdirSync(e,{withFileTypes:!0})){let n=k.default.join(e,o.name),r=k.default.join(t,o.name);o.isDirectory()?(h.default.mkdirSync(r,{recursive:!0}),Oo(n,r)):h.default.copyFileSync(n,r)}}function Zs(){try{try{(0,E.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,E.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,E.execSync)("sleep 1",{stdio:"pipe"});let e=(0,E.execSync)("which badgerclaw",{stdio:"pipe"}).toString().trim();(0,E.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,E.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function ea(){let e=k.default.join(ke.default.homedir(),".badgerclaw","workspace");h.default.mkdirSync(e,{recursive:!0});let t=k.default.join(e,".git");return h.default.existsSync(t)||(0,E.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),h.default.writeFileSync(k.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
69
69
 
70
70
  When you receive a message, it will be formatted like:
71
71
  [Room: RoomName] Sender: message text
@@ -74,14 +74,14 @@ Reply using the reply tool with botId="..." and roomId="..."
74
74
  ALWAYS use the \`reply\` MCP tool to send your response back to the chat room.
75
75
  Use the exact botId and roomId provided in the message \u2014 do not modify them.
76
76
  Keep responses concise and helpful.
77
- `),e}function Fs(){try{h.default.mkdirSync(S.default.dirname(Pt),{recursive:!0});try{let e=h.default.statSync(Pt);if(Date.now()-e.mtimeMs<6e4)return!1;h.default.unlinkSync(Pt)}catch{}return h.default.writeFileSync(Pt,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function Gs(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!Fs())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 ze(e.bot_id),{launchClaudeCode:o,recordSession:n,getActiveSessions:r,stopSession:s}=(Et(),Oo(Io)),a=new Set;try{let E=(await L.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let f of E)if(f.botId!==t&&f.enabled!==!1){let v=f.port;typeof v=="number"&&v>=7332&&a.add(v)}}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 l=7332;for(;a.has(l);)l++;let c=r();for(let p of c)p.port===l&&(console.log(`[command-executor] Stopping existing session ${p.sessionId} on port ${l}`),s(p.sessionId));try{(0,A.execSync)(`lsof -ti :${l} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let i=e.session_id||`session-${Date.now()}`;await L.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:i,port:l},{timeout:1e4});let u=Us();return o({sessionId:i,port:l,projectDir:u}),n(i,0,0,l,u),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${i}, port: ${l})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function ze(e){if(e.startsWith("@"))return e;try{let o=(await L.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],n=S.default.join(be.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 Hs(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 ze(e.bot_id),o=e.session_id;if(!o)try{let n=await L.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 L.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:n}=(Et(),Oo(Io));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 Vs(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 ze(t));let n=e?.session_id||`cc-${Date.now()}`;return await L.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 Ws(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 ze(t)),await L.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 Ks(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 ze(t)),await L.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 qs(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 L.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 Js(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 L.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 Ys(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 L.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 zs(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=S.default.join(be.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 Xs(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 L.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,S,be,L,Pt,xo=N(()=>{"use strict";A=require("child_process"),h=d(require("fs")),S=d(require("path")),be=d(require("os")),L=d(require("axios"));ie();Pt=S.default.join(be.default.homedir(),".badgerclaw","claude-code.lock")});var or={};Nt(or,{heartbeatCommand:()=>Ro,pushHeartbeat:()=>D});function Dt(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 Ot)n-s>oa&&Ot.delete(r);return Ot.has(o)?!0:(Ot.set(o,n),!1)}function er(e,t){let o=st();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:fe(),hermes_containers:un(),bots:e.bots.map(n=>({bot_id:n.botId,bot_username:n.botUsername,status:n.status,activity_state:n.activityState||"idle",active_task:n.activeTask||null,last_activity_at:n.lastActivity,messages_received:n.messagesReceived,messages_sent:n.messagesSent,chunked_messages:n.chunkedMessages,total_chunks_sent:n.totalChunksSent,errors:n.errors,last_error:n.lastError,last_error_at:n.lastErrorAt,uptime_seconds:n.uptimeSeconds,rooms_active:n.roomsActive,room_details:(n.roomDetails||[]).map(r=>({roomId:r.roomId,roomName:r.roomName,workspaceName:r.workspaceName||null,messagesInRoom:r.messagesInRoom,lastActivityInRoom:r.lastActivityInRoom})),claude_code_enabled:n.claudeCodeEnabled??!1,claude_code_session_id:n.claudeCodeSessionId??null,quarantined:n.quarantined??!1}))}}async function D(){let{version:e}=ge(),t=await Ke(),o=er(t,e);await P().post(Zn,o)}function na(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 zn(){try{let o=(await P().get(ea)).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 Qn.default.post("http://localhost:7331/bot-share/sync",n,{timeout:1e4}),console.log(g.default.dim(` [${$()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(g.default.dim(` [${$()}] Share sync failed (non-fatal): ${e.message}`))}}async function ra(){if(!Yn){Yn=!0;try{await P().post(Zs,{instance_id:q()},{timeout:ta}),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 tr(){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(` [${$()}] Token expires soon \u2014 refreshing proactively...`)),await Ft())console.log(g.default.green(` [${$()}] Token refreshed successfully`));else{let s=Fo()||"unknown reason";console.log(g.default.yellow(` [${$()}] Token refresh failed: ${s}`))}}function aa(e,t){let o=3e3,n=3e4,r=null;async function s(){try{await tr();let l=_()?.access_token||e,c=require("eventsource"),i=new c(`${B}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${l}`}});i.onopen=()=>{o=3e3,console.log(g.default.dim(` [${$()}] SSE connected \u2014 listening for real-time events`)),r&&clearTimeout(r),r=setTimeout(()=>{console.log(g.default.dim(` [${$()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),i.close(),s()},sa)},i.onmessage=async u=>{try{let p=JSON.parse(u.data);await ia(p)}catch{}},i.onerror=async()=>{i.close(),r&&(clearTimeout(r),r=null),console.log(g.default.dim(` [${$()}] 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(` [${$()}] SSE connection failed: ${a.message}`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}s()}function $(){return new Date().toISOString()}async function ia(e){if(e.type==="pair"){console.log(g.default.cyan(` [${$()}] Pair event: ${e.bot_name}`)),await Ue(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(` [${$()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await D()}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(` [${$()}] 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(pe(()=>{let c=JSON.parse(n.readFileSync(a,"utf-8")),i=!1;if(c.channels?.badgerclaw?.accounts?.[o]&&(delete c.channels.badgerclaw.accounts[o],i=!0),c.agents?.list){let u=c.agents.list.length;c.agents.list=c.agents.list.filter(p=>p.id!==o),c.agents.list.length!==u&&(i=!0)}return i&&n.writeFileSync(a,JSON.stringify(c,null,2)),i})){console.log(g.default.green(` [${$()}] Removed "${o}" from openclaw.json`));let{execSync:c}=await import("child_process");try{c("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(` [${$()}] Gateway restarted`))}catch{}}}catch(n){console.log(g.default.red(` [${$()}] Failed to clean up bot: ${n}`))}try{await D()}catch{}}else if(e.type==="gateway-restart"){console.log(g.default.cyan(` [${$()}] Remote gateway-restart received`));let t=await ke();console.log(t.success?g.default.green(` [${$()}] Gateway restarted`):g.default.red(` [${$()}] Gateway restart failed: ${t.message}`));try{await D()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(g.default.cyan(` [${$()}] Claude Code START: bot=${e.bot_id}`)),Dt("start_claude_code",e.bot_id)){console.log(g.default.dim(` [${$()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await ee({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 P().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await D()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(g.default.cyan(` [${$()}] Claude Code STOP: bot=${e.bot_id}`)),Dt("stop_claude_code",e.bot_id)){console.log(g.default.dim(` [${$()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await ee({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 P().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await D()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(g.default.cyan(` [${$()}] Command: ${e.command_type} (${e.command_id})`)),Dt(e.command_type,e.payload?.bot_id)){console.log(g.default.dim(` [${$()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=P();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await ee({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(` [${$()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await D()}catch{}}}var Xn,g,Qn,Jn,Qs,Zn,Zs,ea,ta,Yn,Ot,oa,Ro,sa,Xe=N(()=>{"use strict";Xn=require("commander"),g=d(require("chalk")),Qn=d(require("axios"));j();ue();$e();he();eo();ie();xo();ne();Ge();ie();je();Ce();Jn=3e4,Qs=15e4,Zn="/api/v1/dashboard/heartbeat",Zs="/api/v1/dashboard/disconnect",ea="/api/v1/me/active-shares",ta=3e3,Yn=!1,Ot=new Map,oa=3e4;Ro=new Xn.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}=ge();console.log(g.default.green(`Heartbeat daemon started (v${t})`)),console.log(g.default.dim(` Instance: ${q()}`)),console.log(g.default.dim(` Interval: ${Jn/1e3}s`)),console.log(g.default.dim(` Press Ctrl+C to stop.
78
- `));let o=null,n=10,r=0,s=async()=>{try{await tr();let c=await Ke(),i=er(c,t);na(o,c)&&o!==null&&console.log(g.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let p=P(),E=await p.post(Zn,i);r=0;let f=c.bots.length,v=c.bots.filter(I=>I.status==="running").length;console.log(g.default.dim(` [${new Date().toISOString()}] gateway=${c.status} bots=${v}/${f} running mem=${i.mem_free_mb}MB free`)),o=c;try{let x=await mn({api:{post:async(W,Pe)=>{let et=await p.post(W,Pe);return{status:et.status,data:et.data}}}});for(let W of x)W.attempted&&(W.posted||W.envUpdated)&&console.log(g.default.cyan(` [${new Date().toISOString()}] Hermes recovery key captured for ${W.bot_id} (posted=${W.posted}, env_updated=${W.envUpdated})`))}catch(I){console.log(g.default.dim(` [${new Date().toISOString()}] Hermes recovery-key retry skipped: ${I.message}`))}let C=E.data?.pending_commands||[],V=!1;for(let I of C)try{if(console.log(g.default.cyan(` [${new Date().toISOString()}] Received command: ${I.command_type} (${I.id})`)),await p.post(`/api/v1/dashboard/commands/${I.id}/ack`),Dt(I.command_type,I.payload?.bot_id)){console.log(g.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${I.command_type}`));continue}let x=await ee(I);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/${I.id}/result`,{status:x.success?"success":"failed",result:x.message,new_version:x.newVersion||null}),I.command_type==="update_cli"&&x.success&&(V=!0)}catch(x){console.log(g.default.dim(` [${new Date().toISOString()}] Command ${I.id} error: ${x.message}`))}if(V){console.log(g.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await D()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(c){c instanceof ve&&(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}): ${c.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=F()!==null;a?await zn():console.log(g.default.dim(` [${$()}] Hermes-only host \u2014 share-sync disabled (no plugin to push to).`)),setInterval(s,Jn),a&&setInterval(zn,Qs),aa(e.access_token,t);let l=c=>{console.log(g.default.yellow(`
79
- [${new Date().toISOString()}] Received ${c} \u2014 posting disconnect and exiting.`)),ra().finally(()=>{process.exit(0)})};process.on("SIGTERM",l),process.on("SIGINT",l),await new Promise(()=>{})});sa=2700*1e3});var $r=require("commander");var xn=require("commander"),z=d(require("chalk")),Rn=d(require("ora")),An=d(require("open")),uo=d(require("os"));var jt=d(require("crypto"));function Do(){return jt.default.randomBytes(32).toString("base64url")}function To(e){return jt.default.createHash("sha256").update(e).digest("base64url")}j();$e();ue();ne();Ge();var $n=d(require("os"));var ht=d(require("fs")),ye=d(require("path")),He=d(require("os")),Ve=require("child_process"),yn="ai.badgerclaw.watch",wn=ye.default.join(He.default.homedir(),"Library","LaunchAgents"),ro=ye.default.join(wn,`${yn}.plist`);function is(){try{return(0,Ve.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function cs(){try{return(0,Ve.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function ls(e){let t=ye.default.join(He.default.homedir(),".badgerclaw"),o=cs(),n=ye.default.dirname(o),r=ye.default.dirname(e),s=[n,r,"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"],a=new Set,l=s.filter(c=>!c||a.has(c)?!1:(a.add(c),!0)).join(":");return`<?xml version="1.0" encoding="UTF-8"?>
77
+ `),e}function ta(){try{h.default.mkdirSync(k.default.dirname(Mt),{recursive:!0});try{let e=h.default.statSync(Mt);if(Date.now()-e.mtimeMs<6e4)return!1;h.default.unlinkSync(Mt)}catch{}return h.default.writeFileSync(Mt,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function oa(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!ta())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 tt(e.bot_id),{launchClaudeCode:o,recordSession:n,getActiveSessions:r,stopSession:s}=(jt(),Ho(Do)),a=new Set;try{let P=(await B.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let f of P)if(f.botId!==t&&f.enabled!==!1){let w=f.port;typeof w=="number"&&w>=7332&&a.add(w)}}catch{}for(let p=7332;p<=7340;p++)try{(0,E.execSync)(`lsof -ti :${p} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(p)}catch{}let l=7332;for(;a.has(l);)l++;let c=r();for(let p of c)p.port===l&&(console.log(`[command-executor] Stopping existing session ${p.sessionId} on port ${l}`),s(p.sessionId));try{(0,E.execSync)(`lsof -ti :${l} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let i=e.session_id||`session-${Date.now()}`;await B.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:i,port:l},{timeout:1e4});let m=ea();return o({sessionId:i,port:l,projectDir:m}),n(i,0,0,l,m),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${i}, port: ${l})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function tt(e){if(e.startsWith("@"))return e;try{let o=(await B.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],n=k.default.join(ke.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 tt(e.bot_id),o=e.session_id;if(!o)try{let n=await B.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 B.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:n}=(jt(),Ho(Do));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 ra(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 tt(t));let n=e?.session_id||`cc-${Date.now()}`;return await B.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 sa(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 tt(t)),await B.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 aa(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 tt(t)),await B.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 ia(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 B.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 ca(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 B.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 la(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 B.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 da(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=k.default.join(ke.default.homedir(),".openclaw","badgerclaw","quarantine",`${o}.json`);try{h.default.rmSync(n,{force:!0})}catch{}try{return(0,E.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 ua(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 B.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 E,h,k,ke,B,Mt,No=j(()=>{"use strict";E=require("child_process"),h=d(require("fs")),k=d(require("path")),ke=d(require("os")),B=d(require("axios"));de();Mt=k.default.join(ke.default.homedir(),".badgerclaw","claude-code.lock")});var ur={};Wt(ur,{heartbeatCommand:()=>To,pushHeartbeat:()=>T});function Ht(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 Ut)n-s>ha&&Ut.delete(r);return Ut.has(o)?!0:(Ut.set(o,n),!1)}function lr(e,t){let o=dt();return{instance_id:Y(),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:_n(),bots:e.bots.map(n=>({bot_id:n.botId,bot_username:n.botUsername,status:n.status,activity_state:n.activityState||"idle",active_task:n.activeTask||null,last_activity_at:n.lastActivity,messages_received:n.messagesReceived,messages_sent:n.messagesSent,chunked_messages:n.chunkedMessages,total_chunks_sent:n.totalChunksSent,errors:n.errors,last_error:n.lastError,last_error_at:n.lastErrorAt,uptime_seconds:n.uptimeSeconds,rooms_active:n.roomsActive,room_details:(n.roomDetails||[]).map(r=>({roomId:r.roomId,roomName:r.roomName,workspaceName:r.workspaceName||null,messagesInRoom:r.messagesInRoom,lastActivityInRoom:r.lastActivityInRoom})),claude_code_enabled:n.claudeCodeEnabled??!1,claude_code_session_id:n.claudeCodeSessionId??null,quarantined:n.quarantined??!1}))}}async function T(){let{version:e}=we(),t=await Xe(),o=lr(t,e);await O().post(cr,o)}function ya(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 sr(){try{let o=(await O().get(ga)).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 ir.default.post("http://localhost:7331/bot-share/sync",n,{timeout:1e4}),console.log(g.default.dim(` [${v()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(g.default.dim(` [${v()}] Share sync failed (non-fatal): ${e.message}`))}}async function wa(){if(!rr){rr=!0;try{await O().post(pa,{instance_id:Y()},{timeout:fa}),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 dr(){let e=S();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(` [${v()}] Token expires soon \u2014 refreshing proactively...`)),await Yt())console.log(g.default.green(` [${v()}] Token refreshed successfully`));else{let s=zo()||"unknown reason";console.log(g.default.yellow(` [${v()}] Token refresh failed: ${s}`))}}function _a(e,t){let o=3e3,n=3e4,r=null;async function s(){try{await dr();let l=S()?.access_token||e,c=require("eventsource"),i=new c(`${U}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${l}`}});i.onopen=()=>{o=3e3,console.log(g.default.dim(` [${v()}] SSE connected \u2014 listening for real-time events`)),r&&clearTimeout(r),r=setTimeout(()=>{console.log(g.default.dim(` [${v()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),i.close(),s()},ba)},i.onmessage=async m=>{try{let p=JSON.parse(m.data);await Sa(p)}catch{}},i.onerror=async()=>{i.close(),r&&(clearTimeout(r),r=null),console.log(g.default.dim(` [${v()}] 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(` [${v()}] SSE connection failed: ${a.message}`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}s()}function v(){return new Date().toISOString()}async function Sa(e){if(e.type==="pair"){console.log(g.default.cyan(` [${v()}] Pair event: ${e.bot_name}`)),await Ve(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(` [${v()}] 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(` [${v()}] 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(ye(()=>{let c=JSON.parse(n.readFileSync(a,"utf-8")),i=!1;if(c.channels?.badgerclaw?.accounts?.[o]&&(delete c.channels.badgerclaw.accounts[o],i=!0),c.agents?.list){let m=c.agents.list.length;c.agents.list=c.agents.list.filter(p=>p.id!==o),c.agents.list.length!==m&&(i=!0)}return i&&n.writeFileSync(a,JSON.stringify(c,null,2)),i})){console.log(g.default.green(` [${v()}] Removed "${o}" from openclaw.json`));let{execSync:c}=await import("child_process");try{c("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(` [${v()}] Gateway restarted`))}catch{}}}catch(n){console.log(g.default.red(` [${v()}] Failed to clean up bot: ${n}`))}try{await T()}catch{}}else if(e.type==="gateway-restart"){console.log(g.default.cyan(` [${v()}] Remote gateway-restart received`));let t=await Ae();console.log(t.success?g.default.green(` [${v()}] Gateway restarted`):g.default.red(` [${v()}] 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(` [${v()}] Claude Code START: bot=${e.bot_id}`)),Ht("start_claude_code",e.bot_id)){console.log(g.default.dim(` [${v()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await ne({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(` [${v()}] Claude Code STOP: bot=${e.bot_id}`)),Ht("stop_claude_code",e.bot_id)){console.log(g.default.dim(` [${v()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await ne({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(` [${v()}] Command: ${e.command_type} (${e.command_id})`)),Ht(e.command_type,e.payload?.bot_id)){console.log(g.default.dim(` [${v()}] 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 ne({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(` [${v()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await T()}catch{}}}var ar,g,ir,nr,ma,cr,pa,ga,fa,rr,Ut,ha,To,ba,ot=j(()=>{"use strict";ar=require("commander"),g=d(require("chalk")),ir=d(require("axios"));M();fe();Ce();be();kt();de();No();se();Ke();de();Fe();Re();nr=3e4,ma=15e4,cr="/api/v1/dashboard/heartbeat",pa="/api/v1/dashboard/disconnect",ga="/api/v1/me/active-shares",fa=3e3,rr=!1,Ut=new Map,ha=3e4;To=new ar.Command("heartbeat").description("Run heartbeat daemon \u2014 reports telemetry to the BadgerClaw dashboard every 30s").action(async()=>{let e=S();e||(console.log(g.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=we();console.log(g.default.green(`Heartbeat daemon started (v${t})`)),console.log(g.default.dim(` Instance: ${Y()}`)),console.log(g.default.dim(` Interval: ${nr/1e3}s`)),console.log(g.default.dim(` Press Ctrl+C to stop.
78
+ `));let o=null,n=10,r=0,s=async()=>{try{await dr();let c=await Xe(),i=lr(c,t);ya(o,c)&&o!==null&&console.log(g.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let p=O(),P=await p.post(cr,i);r=0;let f=c.bots.length,w=c.bots.filter(C=>C.status==="running").length;console.log(g.default.dim(` [${new Date().toISOString()}] gateway=${c.status} bots=${w}/${f} running mem=${i.mem_free_mb}MB free`)),o=c;try{let R=await Sn({api:{post:async(K,Le)=>{let st=await p.post(K,Le);return{status:st.status,data:st.data}}}});for(let K of R)K.attempted&&(K.posted||K.envUpdated)&&console.log(g.default.cyan(` [${new Date().toISOString()}] Hermes recovery key captured for ${K.bot_id} (posted=${K.posted}, env_updated=${K.envUpdated})`))}catch(C){console.log(g.default.dim(` [${new Date().toISOString()}] Hermes recovery-key retry skipped: ${C.message}`))}let A=P.data?.pending_commands||[],$=!1;for(let C of A)try{if(console.log(g.default.cyan(` [${new Date().toISOString()}] Received command: ${C.command_type} (${C.id})`)),await p.post(`/api/v1/dashboard/commands/${C.id}/ack`),Ht(C.command_type,C.payload?.bot_id)){console.log(g.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${C.command_type}`));continue}let R=await ne(C);console.log(R.success?g.default.green(` [${new Date().toISOString()}] ${R.message}`):g.default.red(` [${new Date().toISOString()}] ${R.message}`)),await p.post(`/api/v1/dashboard/commands/${C.id}/result`,{status:R.success?"success":"failed",result:R.message,new_version:R.newVersion||null}),C.command_type==="update_cli"&&R.success&&($=!0)}catch(R){console.log(g.default.dim(` [${new Date().toISOString()}] Command ${C.id} error: ${R.message}`))}if($){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(c){c instanceof Ie&&(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}): ${c.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=W()!==null;a?await sr():console.log(g.default.dim(` [${v()}] Hermes-only host \u2014 share-sync disabled (no plugin to push to).`)),setInterval(s,nr),a&&setInterval(sr,ma),_a(e.access_token,t);let l=c=>{console.log(g.default.yellow(`
79
+ [${new Date().toISOString()}] Received ${c} \u2014 posting disconnect and exiting.`)),wa().finally(()=>{process.exit(0)})};process.on("SIGTERM",l),process.on("SIGINT",l),await new Promise(()=>{})});ba=2700*1e3});var Lr=require("commander");var Ln=require("commander"),Q=d(require("chalk")),Bn=d(require("ora")),jn=d(require("open")),wo=d(require("os"));var Vt=d(require("crypto"));function Fo(){return Vt.default.randomBytes(32).toString("base64url")}function Go(e){return Vt.default.createHash("sha256").update(e).digest("base64url")}M();Ce();fe();se();Ke();var Pn=d(require("os"));var $t=d(require("fs")),_e=d(require("path")),Je=d(require("os")),Ye=require("child_process"),In="ai.badgerclaw.watch",Rn=_e.default.join(Je.default.homedir(),"Library","LaunchAgents"),mo=_e.default.join(Rn,`${In}.plist`);function Ss(){try{return(0,Ye.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function ks(){try{return(0,Ye.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function vs(e){let t=_e.default.join(Je.default.homedir(),".badgerclaw"),o=ks(),n=_e.default.dirname(o),r=_e.default.dirname(e),s=[n,r,"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"],a=new Set,l=s.filter(c=>!c||a.has(c)?!1:(a.add(c),!0)).join(":");return`<?xml version="1.0" encoding="UTF-8"?>
80
80
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
81
81
  <plist version="1.0">
82
82
  <dict>
83
83
  <key>Label</key>
84
- <string>${yn}</string>
84
+ <string>${In}</string>
85
85
  <key>ProgramArguments</key>
86
86
  <array>
87
87
  <string>${o}</string>
@@ -104,7 +104,7 @@ Keep responses concise and helpful.
104
104
  <key>ThrottleInterval</key>
105
105
  <integer>30</integer>
106
106
  </dict>
107
- </plist>`}function bn(){if(He.default.platform()==="darwin")try{let e=is();ht.default.mkdirSync(wn,{recursive:!0}),ht.default.mkdirSync(ye.default.join(He.default.homedir(),".badgerclaw"),{recursive:!0}),ht.default.writeFileSync(ro,ls(e));try{(0,Ve.execSync)(`launchctl unload "${ro}" 2>/dev/null`)}catch{}(0,Ve.execSync)(`launchctl load "${ro}"`),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")}}var yt=d(require("fs")),We=d(require("path")),wt=d(require("os")),Q=require("child_process"),so="badgerclaw-watch.service",_n=We.default.join(wt.default.homedir(),".config","systemd","user"),ds=We.default.join(_n,so);function us(){try{return(0,Q.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function ms(){try{return(0,Q.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function ps(e){let t=ms(),o=We.default.dirname(t);return`[Unit]
107
+ </plist>`}function xn(){if(Je.default.platform()==="darwin")try{let e=Ss();$t.default.mkdirSync(Rn,{recursive:!0}),$t.default.mkdirSync(_e.default.join(Je.default.homedir(),".badgerclaw"),{recursive:!0}),$t.default.writeFileSync(mo,vs(e));try{(0,Ye.execSync)(`launchctl unload "${mo}" 2>/dev/null`)}catch{}(0,Ye.execSync)(`launchctl load "${mo}"`),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")}}var Ct=d(require("fs")),ze=d(require("path")),It=d(require("os")),te=require("child_process"),po="badgerclaw-watch.service",An=ze.default.join(It.default.homedir(),".config","systemd","user"),$s=ze.default.join(An,po);function Cs(){try{return(0,te.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function Is(){try{return(0,te.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function Rs(e){let t=Is(),o=ze.default.dirname(t);return`[Unit]
108
108
  Description=BadgerClaw background watcher (heartbeat + pair events)
109
109
  After=network-online.target
110
110
  Wants=network-online.target
@@ -120,38 +120,40 @@ StandardError=append:%h/.badgerclaw/heartbeat.log
120
120
 
121
121
  [Install]
122
122
  WantedBy=default.target
123
- `}function gs(){try{return(0,Q.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function Sn(){if(wt.default.platform()==="linux"){if(!gs()){console.log("\x1B[2mNote: systemctl --user not available. Run `badgerclaw heartbeat` manually or start it under a process manager.\x1B[0m");return}try{let e=us();yt.default.mkdirSync(_n,{recursive:!0}),yt.default.mkdirSync(We.default.join(wt.default.homedir(),".badgerclaw"),{recursive:!0}),yt.default.writeFileSync(ds,ps(e)),(0,Q.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,Q.execSync)(`systemctl --user restart ${so}`,{stdio:"ignore"})}catch{}(0,Q.execSync)(`systemctl --user enable --now ${so}`,{stdio:"ignore"});try{let t=(0,Q.execSync)("whoami",{encoding:"utf-8"}).trim();(0,Q.execSync)(`loginctl enable-linger ${t}`,{stdio:"ignore"})}catch{}console.log("\x1B[2mHeartbeat daemon registered as systemd user service (auto-starts on login).\x1B[0m")}catch{console.log("\x1B[2mNote: could not register systemd user service. Run `badgerclaw heartbeat` manually.\x1B[0m")}}}function vn(){let e=$n.default.platform();if(e==="darwin")return bn();if(e==="linux")return Sn();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var ce=d(require("fs")),lo=d(require("os")),_t=d(require("path")),Y=require("child_process"),M=d(require("chalk"));je();ie();var In=_t.default.join(lo.default.homedir(),".openclaw","openclaw.json");function ws(){return process.platform!=="linux"?!1:!!(ce.default.existsSync("/.dockerenv")||(0,Y.spawnSync)("which",["systemctl"],{encoding:"utf-8"}).status!==0)}function kn(e=!1){let t=null;try{ce.default.existsSync(In)&&(t=JSON.parse(ce.default.readFileSync(In,"utf-8"))?.gateway?.mode??null)}catch{}if(typeof t=="string"&&t.length>0)return!0;e||console.log(M.default.dim(" Setting gateway.mode=local..."));try{return pe(()=>((0,Y.execSync)("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),!0))}catch(o){return e||(console.log(M.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${o.message}`)),console.log(M.default.yellow(" Run `openclaw config set gateway.mode local` manually."))),!1}}async function St(e={}){let t=e.verbose!==!1,o=l=>{t&&console.log(l)};if(ws())return _s(t);o(M.default.dim(" Installing OpenClaw gateway service (if not present)...")),(0,Y.spawnSync)("openclaw",["gateway","install"],{stdio:t?"inherit":"pipe",shell:!0}).status!==0&&o(M.default.yellow(" \u26A0\uFE0F `openclaw gateway install` returned non-zero \u2014 continuing.")),kn(!t),o(M.default.dim(" Starting OpenClaw gateway..."));let r=(0,Y.spawnSync)("openclaw",["gateway","start"],{stdio:t?"inherit":"pipe",shell:!0}),s="started";if(r.status!==0&&(r=(0,Y.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(M.default.dim(" Waiting for the gateway to start answering..."));let a=await bs(2e4);return a||o(M.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 bs(e,t=io,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 _s(e){let t=i=>{e&&console.log(i)};t(M.default.dim(" Container mode (no systemd) \u2014 running gateway in foreground via nohup.")),kn(!e);let o=_t.default.join(lo.default.homedir(),".openclaw","logs");try{ce.default.mkdirSync(o,{recursive:!0})}catch{}let n=_t.default.join(o,"gateway-foreground.log"),r,s;try{r=ce.default.openSync(n,"a"),s=ce.default.openSync(n,"a")}catch(i){return{ok:!1,error:`cannot open gateway log at ${n}: ${i.message}`}}let a=(0,Y.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(M.default.dim(` Gateway PID: ${a.pid}, log: ${n}`));let l=Date.now()+2e4,c=!1;for(;Date.now()<l;){try{let i=ce.default.readFileSync(n,"utf-8");if(i.includes("[gateway] ready")){c=!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 c?{ok:!0,state:"started",ready:!0}:{ok:!1,error:`gateway did not report ready within 20s \u2014 see ${n}`}}function $t(){if(process.platform!=="linux"||process.getuid?.()!==0)return;let e=(0,Y.spawnSync)("loginctl",["show-user","root","--property=Linger"],{encoding:"utf-8"});e.status===0&&/Linger=no/.test(e.stdout||"")&&(console.log(M.default.yellow(`
124
- \u26A0\uFE0F systemd lingering is OFF for root. The gateway will stop on SSH disconnect.`)),console.log(M.default.dim(" Enable persistence: loginctl enable-linger root")))}Ce();var Ss=2e3,$s=12e4,En=new xn.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=Do(),t=To(e),o=`${Mo}/cli-auth?code=${t}`;console.log(z.default.yellow("Opening browser for authentication...")),console.log(z.default.dim(`If the browser doesn't open, visit: ${o}`)),await(0,An.default)(o);let n=(0,Rn.default)("Waiting for authentication...").start(),r=Vo(),s=Date.now();for(;Date.now()-s<$s;){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(l=>setTimeout(l,5e3));continue}if(a.data?.access_token){let{access_token:l,user_id:c,expires_at:i,refresh_token:u,email:p}=a.data,E=Ut(),f=`openclaw-${uo.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${E}`,v=f;try{let{version:V}=ge(),I=await r.post("/api/v1/openclaw/register",{instance_id:f,label:uo.default.hostname(),version:V,machine_fingerprint:E},{headers:{Authorization:`Bearer ${l}`}}),x=I.data?.result||I.data;x&&typeof x.instance_id=="string"&&x.instance_id.length>0&&(v=x.instance_id)}catch(V){let I=V?.response?.status;if(I===403||I===409){let x=V?.response?.data,W=Array.isArray(x?.errors)&&typeof x.errors[0]=="string"?x.errors[0]:null,Pe=x?.detail,et=typeof Pe=="string"?Pe:Pe?.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,vr=W||et||`Login refused (status ${I}). Open the BadgerClaw app to check your subscription state.`;n.fail(z.default.red(vr)),process.exit(1)}}if(ot({access_token:l,user_id:c,instance_id:v,expires_at:i,refresh_token:u,email:p}),n.succeed(z.default.green(`Logged in as ${rt(c)}`)),F()!==null){let V=await St({verbose:!0});V.ok?V.ready===!1&&console.log(z.default.dim(" Gateway is still coming up \u2014 it should be online shortly.")):console.log(z.default.yellow("\n \u26A0\uFE0F Logged in, but gateway failed to start. Re-run `badgerclaw setup` to repair."))}else console.log(z.default.dim(" Hermes-only host \u2014 skipping OpenClaw gateway bring-up."));let C=await Fe(!0);C>0&&console.log(z.default.green(`\u2705 ${C} bot(s) automatically paired to OpenClaw.`)),vn(),$t();return}}catch{}await new Promise(a=>setTimeout(a,Ss))}n.fail(z.default.red("Authentication timed out. Please try again.")),process.exit(1)});var On=require("commander"),qe=d(require("chalk")),vt=d(require("fs")),xe=d(require("os")),Ye=d(require("path")),Je=require("child_process");j();ue();function vs(){let e=process.platform;if(e==="darwin"){let t=Ye.default.join(xe.default.homedir(),"Library","LaunchAgents","ai.badgerclaw.watch.plist");(0,Je.spawnSync)("launchctl",["unload",t],{stdio:"ignore"});try{vt.default.unlinkSync(t)}catch{}}else if(e==="linux"){(0,Je.spawnSync)("systemctl",["--user","disable","--now","badgerclaw-watch.service"],{stdio:"ignore"});let t=Ye.default.join(xe.default.homedir(),".config","systemd","user","badgerclaw-watch.service");try{vt.default.unlinkSync(t)}catch{}(0,Je.spawnSync)("systemctl",["--user","daemon-reload"],{stdio:"ignore"})}(0,Je.spawnSync)("pkill",["-f","badgerclaw heartbeat"],{stdio:"ignore"})}function Pn(e){try{return vt.default.rmSync(e,{recursive:!0,force:!0}),!0}catch{return!1}}var Dn=new On.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=Ne(t.access_token),{version:l}=ge();await a.post("/api/v1/openclaw/register",{instance_id:t.instance_id,label:xe.default.hostname(),version:l,online:!1})}catch{}if(vs(),e.keepState){De(),console.log(qe.default.green("Logged out \u2014 auth cleared. (state preserved with --keep-state)"));return}let o=Ye.default.join(xe.default.homedir(),".badgerclaw"),n=Pn(o),r=Ye.default.join(xe.default.homedir(),".openclaw","badgerclaw"),s=Pn(r);n||s?(console.log(qe.default.green("Logged out \u2014 local state cleared.")),console.log(qe.default.dim(` Removed: ${o}${s?`, ${r}`:""}`))):console.log(qe.default.green("Logged out."))});var Tn=require("commander"),mo=d(require("chalk"));j();var Ln=new Tn.Command("status").description("Show connected instance info").action(async()=>{let e=_();(!e||!nt())&&(console.log(mo.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(mo.default.green("Authenticated")),console.log(` User: ${rt(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var Ae=require("commander"),w=d(require("chalk")),xt=d(require("ora")),kt=d(require("fs")),Fn=d(require("os")),Gn=d(require("path")),Hn=require("child_process");j();ue();var Re=d(require("fs")),Nn=d(require("os")),jn=d(require("path")),Bn=require("child_process");je();function Ct(e){let t=e.split(":")[0].replace(/^@/,"").replace(/_bot$/,""),o=jn.join(Nn.homedir(),".openclaw","openclaw.json");return Re.existsSync(o)?{changed:pe(()=>{let r=JSON.parse(Re.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(l=>l.id!==t),r.agents.list.length!==a&&(s=!0)}return s&&Re.writeFileSync(o,JSON.stringify(r,null,2)),s})}:{changed:!1}}function It(){try{return(0,Bn.execSync)("openclaw gateway restart",{stdio:"ignore"}),!0}catch{return!1}}he();function Mn(e){return e.hermes?"hermes":"openclaw"}function Un(e){return e.openclaw.installed?"openclaw":e.hermes.installed?"hermes":"openclaw"}function go(){nt()||(console.log(w.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function Cs(e){return/^[a-z0-9_]{4,20}$/.test(e)}function Vn(e){return e.replace(/_bot$/,"")}var po=["openclaw","hermes"],Is=new Ae.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").option("-r, --runtime <runtime>",`Bot runtime: ${po.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)=>{go(),Cs(e)||(console.log(w.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let o=t.runtime??Un(fe());po.includes(o)||(console.log(w.default.red(`Invalid --runtime "${t.runtime}". Must be one of: ${po.join(", ")}.`)),process.exit(1));let n=(0,xt.default)(`Creating ${o} bot "${e}"...`).start();try{let r=P();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(w.default.green(`Bot "${e}" (${o}) created successfully!`)),o==="hermes"&&console.log(w.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(w.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),ks=new Ae.Command("list").description("List your bots").action(async()=>{go();let e=(0,xt.default)("Fetching bots...").start();try{let n=(await P().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),n.length===0){console.log(w.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(w.default.green(`Your bots (${n.length}):
125
- `));for(let r of n){let s=Vn(r.username||r.name),a=r.active===!1?w.default.dim("deactivated"):r.openclaw_connected?w.default.green("connected"):w.default.gray("disconnected");console.log(` ${w.default.bold(s)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(w.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),xs=new Ae.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{go();let t=(0,xt.default)(`Deactivating bot "${e}"...`).start();try{await P().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(w.default.green(`Bot "${e}" deactivated.`));let{changed:n}=Ct(e);n&&(console.log(w.default.dim(" Removed from openclaw.json")),It()&&console.log(w.default.dim(" Gateway restarted")))}catch(o){let n=o.response?.data?.errors?.[0]||o.message;t.fail(w.default.red(`Failed to deactivate bot: ${n}`)),process.exit(1)}});function Rs(e){let t=e.trim();return t.startsWith("@")&&(t=t.slice(1)),t.includes(":")&&(t=t.split(":")[0]),Vn(t)}function As(e){let t=e.replace(/[^a-zA-Z0-9_.-]/g,"_")||"default";return Gn.default.join(Fn.default.homedir(),".openclaw","badgerclaw","quarantine",`${t}.json`)}var Es=new Ae.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=Rs(e);t||(console.log(w.default.red(`Couldn't parse bot name "${e}".`)),process.exit(1));let o=As(t),n=!1;if(kt.default.existsSync(o))try{let r=JSON.parse(kt.default.readFileSync(o,"utf-8")),s=r.failureCount??"?",a=r.quarantinedAt??"?";console.log(w.default.dim(` Quarantine for "${t}" \u2014 ${s} failures, since ${a}`)),kt.default.unlinkSync(o),n=!0}catch(r){console.log(w.default.red(`Failed to clear quarantine ledger at ${o}: ${r.message}`)),process.exit(1)}console.log(n?w.default.green(`\u2705 Cleared quarantine for "${t}"`):w.default.dim(` No quarantine file for "${t}" \u2014 already healthy or never quarantined.`)),console.log(w.default.dim(" Restarting OpenClaw gateway so the refresh chain runs..."));try{(0,Hn.execSync)("openclaw gateway restart",{stdio:"inherit"})}catch(r){console.log(w.default.yellow(` Gateway restart command failed: ${r.message}`)),console.log(w.default.yellow(" Run `openclaw gateway restart` manually.")),process.exit(1)}console.log(w.default.green(`
126
- \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(w.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(w.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(w.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(w.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),Wn=new Ae.Command("bot").description("Manage bots").addCommand(Is).addCommand(ks).addCommand(xs).addCommand(Es);Ge();var rr=require("commander"),y=d(require("chalk"));j();ne();Ge();ie();Xe();xo();ue();$e();var nr=3e3,ca=6e4,la=2700*1e3,sr=new rr.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 Fe(!1),console.log(y.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=nr,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 l=new t(`${B}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${a.access_token}`}});r=l,l.onopen=()=>{o=nr,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")),l.close(),s()},la)},l.onerror=()=>{l.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,ca)},l.onmessage=async c=>{try{let i=JSON.parse(c.data);if(i.type==="pair"){let u=i.target_instance_id;if(u&&u!==q()){console.log(y.default.dim(`
127
- \u{1F4F1} Pair event for ${i.bot_name} targets ${u} \u2014 not us, skipping`));return}console.log(y.default.cyan(`
128
- \u{1F4F1} Pair event received: ${i.bot_name}`)),await Ue(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(`
129
- \u{1F504} Remote gateway-restart command received`));let u=await ke();u.success?console.log(y.default.green(` \u2705 Gateway restarted: ${u.message}`)):console.log(y.default.red(` \u274C Gateway restart failed: ${u.message}`));try{await D(),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 u=i.bot_user_id,p=i.type==="bot.delete"?"deleted":"disconnected",E=i.type==="bot.delete"?"\u{1F5D1}\uFE0F ":"\u{1F50C}";console.log(y.default.yellow(`
130
- ${E} Bot ${p}: ${u} \u2014 removing from OpenClaw config...`));try{let{changed:f}=Ct(u);f?(console.log(y.default.green(" \u2705 Removed from openclaw.json")),It()?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(f){console.log(y.default.red(` Failed to update openclaw.json: ${f}`))}}else if(i.type==="claude_code.start"&&i.bot_id&&i.room_id){console.log(y.default.cyan(`
131
- \u{1F916} Claude Code START received: bot=${i.bot_id} room=${i.room_id}`));try{let u=await ee({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(u.success?y.default.green(` \u2705 ${u.message}`):y.default.red(` \u274C ${u.message}`)),i.command_id)try{await P().post(`/api/v1/dashboard/commands/${i.command_id}/result`,{status:u.success?"success":"failed",result:u.message})}catch{}try{await D()}catch{}}catch(u){console.log(y.default.red(` Claude Code start error: ${u.message}`))}}else if(i.type==="claude_code.stop"&&i.bot_id&&i.room_id){console.log(y.default.cyan(`
132
- \u{1F916} Claude Code STOP received: bot=${i.bot_id} room=${i.room_id}`));try{let u=await ee({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(u.success?y.default.green(` \u2705 ${u.message}`):y.default.red(` \u274C ${u.message}`)),i.command_id)try{await P().post(`/api/v1/dashboard/commands/${i.command_id}/result`,{status:u.success?"success":"failed",result:u.message})}catch{}try{await D()}catch{}}catch(u){console.log(y.default.red(` Claude Code stop error: ${u.message}`))}}else if(i.type==="command.execute"&&i.command_id){console.log(y.default.cyan(`
133
- \u26A1 SSE command received: ${i.command_type} (${i.command_id})`));try{let u=P();await u.post(`/api/v1/dashboard/commands/${i.command_id}/ack`);let p=await ee({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 u.post(`/api/v1/dashboard/commands/${i.command_id}/result`,{status:p.success?"success":"failed",result:p.message,new_version:p.newVersion||null});try{await D()}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(u){console.log(y.default.red(` Command ${i.command_id} error: ${u.message}`))}}}catch{}}};s(),await new Promise(()=>{})});var pr=require("commander"),m=d(require("chalk")),te=require("child_process"),k=d(require("fs")),Ze=d(require("os")),oe=d(require("path"));ne();Ce();he();var ar=require("child_process"),Tt=d(require("fs")),ir=d(require("os")),Lt=d(require("path"));he();function da(){let e=cr();for(let t of e)if(Tt.default.existsSync(t))return t;return null}function cr(){return[Lt.default.resolve(__dirname,"..","assets","hermes-agent-bc.Dockerfile"),Lt.default.resolve(__dirname,"..","..","assets","hermes-agent-bc.Dockerfile")]}var ua="nousresearch/hermes-agent";function ma(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`${ua}:${o}`}function lr(e){let t=ut();if(!t.installed)return{status:"no-docker"};let o=process.env.HERMES_IMAGE||Ie;if(mt(t).installed)return{status:"already-present",image:o};let r=da();if(!r)return{status:"no-dockerfile",expectedPaths:cr()};let s=ma(e),a=s?["--build-arg",`UPSTREAM=${s}`]:[],l=Tt.default.mkdtempSync(Lt.default.join(ir.default.tmpdir(),"bc-hermes-build-"));try{let c=(0,ar.spawnSync)("docker",["build",...a,"-t",o,"-f",r,l],{stdio:"inherit",timeout:6e5});return c.status===0?{status:"built",image:o}:{status:"build-failed",image:o,stderr:`docker build exited ${c.status??"<no-status>"}`}}finally{try{Tt.default.rmSync(l,{recursive:!0,force:!0})}catch{}}}var H=oe.default.join(Ze.default.homedir(),".openclaw","openclaw.json"),Qe=H+".badgerclaw-stash",gr=oe.default.join(Ze.default.homedir(),".openclaw","npm"),pa=oe.default.join(gr,"package.json");async function dr(){try{let e=await fetch(`${B}/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 ga(){if(!k.default.existsSync(H))return null;try{let e=JSON.parse(k.default.readFileSync(H,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,k.default.writeFileSync(H,JSON.stringify(e,null,2)),k.default.writeFileSync(Qe,JSON.stringify(t,null,2)),t):null}catch{return null}}function fa(){if(!k.default.existsSync(H))return null;try{let e=JSON.parse(k.default.readFileSync(H,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function ha(e){if(e&&k.default.existsSync(H))try{let t=JSON.parse(k.default.readFileSync(H,"utf-8"));t.gateway={...e,...t.gateway||{}},k.default.writeFileSync(H,JSON.stringify(t,null,2))}catch(t){console.log(m.default.yellow(` \u26A0\uFE0F Could not restore gateway block: ${t.message}`)),console.log(m.default.yellow(" Run `openclaw config set gateway.mode local` manually if the gateway fails to start."))}}function ya(){if(k.default.existsSync(Qe))try{let e=JSON.parse(k.default.readFileSync(Qe,"utf-8")),t=JSON.parse(k.default.readFileSync(H,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,k.default.writeFileSync(H,JSON.stringify(t,null,2)),k.default.unlinkSync(Qe)}catch(e){console.log(m.default.yellow(` \u26A0\uFE0F Could not restore config: ${e.message}`)),console.log(m.default.yellow(` Your bot credentials are backed up at: ${Qe}`))}}async function ur(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/,l=()=>{r||s||(r=!0,setTimeout(()=>{if(!s){try{o.kill("SIGTERM")}catch{}setTimeout(()=>{if(!s)try{o.kill("SIGKILL")}catch{}},1e3)}},3e3))},c=(i,u)=>{u.write(i),n+=i.toString("utf-8"),a.test(n)&&l()};o.stdout.on("data",i=>c(i,process.stdout)),o.stderr.on("data",i=>c(i,process.stderr)),o.on("exit",i=>{s=!0,t({status:r?0:i??1})}),o.on("error",i=>{s||(s=!0,console.error(m.default.red(` openclaw spawn error: ${i.message}`)),t({status:1}))})})}function mr(e){if(!k.default.existsSync(e))return!1;let t;try{t=JSON.parse(k.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?(k.default.writeFileSync(e,JSON.stringify(t,null,2)+`
134
- `),!0):!1}function wa(){let e=[];mr(pa)&&e.push(gr);for(let t of lt())mr(oe.default.join(t,"package.json"))&&e.push(t);return e}async function ba(){let{detectCapabilities:e}=await Promise.resolve().then(()=>(he(),nn)),{pushHeartbeat:t}=await Promise.resolve().then(()=>(Xe(),or));console.log(m.default.green(`
123
+ `}function xs(){try{return(0,te.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function En(){if(It.default.platform()==="linux"){if(!xs()){console.log("\x1B[2mNote: systemctl --user not available. Run `badgerclaw heartbeat` manually or start it under a process manager.\x1B[0m");return}try{let e=Cs();Ct.default.mkdirSync(An,{recursive:!0}),Ct.default.mkdirSync(ze.default.join(It.default.homedir(),".badgerclaw"),{recursive:!0}),Ct.default.writeFileSync($s,Rs(e)),(0,te.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,te.execSync)(`systemctl --user restart ${po}`,{stdio:"ignore"})}catch{}(0,te.execSync)(`systemctl --user enable --now ${po}`,{stdio:"ignore"});try{let t=(0,te.execSync)("whoami",{encoding:"utf-8"}).trim();(0,te.execSync)(`loginctl enable-linger ${t}`,{stdio:"ignore"})}catch{}console.log("\x1B[2mHeartbeat daemon registered as systemd user service (auto-starts on login).\x1B[0m")}catch{console.log("\x1B[2mNote: could not register systemd user service. Run `badgerclaw heartbeat` manually.\x1B[0m")}}}function Dn(){let e=Pn.default.platform();if(e==="darwin")return xn();if(e==="linux")return En();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var ue=d(require("fs")),yo=d(require("os")),xt=d(require("path")),X=require("child_process"),H=d(require("chalk"));Fe();de();var Nn=xt.default.join(yo.default.homedir(),".openclaw","openclaw.json");function Ds(){return process.platform!=="linux"?!1:!!(ue.default.existsSync("/.dockerenv")||(0,X.spawnSync)("which",["systemctl"],{encoding:"utf-8"}).status!==0)}function Tn(e=!1){let t=null;try{ue.default.existsSync(Nn)&&(t=JSON.parse(ue.default.readFileSync(Nn,"utf-8"))?.gateway?.mode??null)}catch{}if(typeof t=="string"&&t.length>0)return!0;e||console.log(H.default.dim(" Setting gateway.mode=local..."));try{return ye(()=>((0,X.execSync)("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),!0))}catch(o){return e||(console.log(H.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${o.message}`)),console.log(H.default.yellow(" Run `openclaw config set gateway.mode local` manually."))),!1}}async function At(e={}){let t=e.verbose!==!1,o=l=>{t&&console.log(l)};if(Ds())return Ns(t);o(H.default.dim(" Installing OpenClaw gateway service (if not present)...")),(0,X.spawnSync)("openclaw",["gateway","install"],{stdio:t?"inherit":"pipe",shell:!0}).status!==0&&o(H.default.yellow(" \u26A0\uFE0F `openclaw gateway install` returned non-zero \u2014 continuing.")),Tn(!t),o(H.default.dim(" Starting OpenClaw gateway..."));let r=(0,X.spawnSync)("openclaw",["gateway","start"],{stdio:t?"inherit":"pipe",shell:!0}),s="started";if(r.status!==0&&(r=(0,X.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(H.default.dim(" Waiting for the gateway to start answering..."));let a=await Os(2e4);return a||o(H.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 Os(e,t=fo,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 Ns(e){let t=i=>{e&&console.log(i)};t(H.default.dim(" Container mode (no systemd) \u2014 running gateway in foreground via nohup.")),Tn(!e);let o=xt.default.join(yo.default.homedir(),".openclaw","logs");try{ue.default.mkdirSync(o,{recursive:!0})}catch{}let n=xt.default.join(o,"gateway-foreground.log"),r,s;try{r=ue.default.openSync(n,"a"),s=ue.default.openSync(n,"a")}catch(i){return{ok:!1,error:`cannot open gateway log at ${n}: ${i.message}`}}let a=(0,X.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(H.default.dim(` Gateway PID: ${a.pid}, log: ${n}`));let l=Date.now()+2e4,c=!1;for(;Date.now()<l;){try{let i=ue.default.readFileSync(n,"utf-8");if(i.includes("[gateway] ready")){c=!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 c?{ok:!0,state:"started",ready:!0}:{ok:!1,error:`gateway did not report ready within 20s \u2014 see ${n}`}}function Et(){if(process.platform!=="linux"||process.getuid?.()!==0)return;let e=(0,X.spawnSync)("loginctl",["show-user","root","--property=Linger"],{encoding:"utf-8"});e.status===0&&/Linger=no/.test(e.stdout||"")&&(console.log(H.default.yellow(`
124
+ \u26A0\uFE0F systemd lingering is OFF for root. The gateway will stop on SSH disconnect.`)),console.log(H.default.dim(" Enable persistence: loginctl enable-linger root")))}Re();var Ts=2e3,Ls=12e4,Mn=new Ln.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=Fo(),t=Go(e),o=`${Jo}/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,jn.default)(o);let n=(0,Bn.default)("Waiting for authentication...").start(),r=Zo(),s=Date.now();for(;Date.now()-s<Ls;){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(l=>setTimeout(l,5e3));continue}if(a.data?.access_token){let{access_token:l,user_id:c,expires_at:i,refresh_token:m,email:p}=a.data,P=Jt(),f=`openclaw-${wo.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${P}`,w=f;try{let{version:$}=we(),C=await r.post("/api/v1/openclaw/register",{instance_id:f,label:wo.default.hostname(),version:$,machine_fingerprint:P},{headers:{Authorization:`Bearer ${l}`}}),R=C.data?.result||C.data;R&&typeof R.instance_id=="string"&&R.instance_id.length>0&&(w=R.instance_id)}catch($){let C=$?.response?.status;if(C===403||C===409){let R=$?.response?.data,K=Array.isArray(R?.errors)&&typeof R.errors[0]=="string"?R.errors[0]:null,Le=R?.detail,st=typeof Le=="string"?Le:Le?.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,Br=K||st||`Login refused (status ${C}). Open the BadgerClaw app to check your subscription state.`;n.fail(Q.default.red(Br)),process.exit(1)}}if(it({access_token:l,user_id:c,instance_id:w,expires_at:i,refresh_token:m,email:p}),n.succeed(Q.default.green(`Logged in as ${lt(c)}`)),W()!==null){let $=await At({verbose:!0});$.ok?$.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 A=await qe(!0);A>0&&console.log(Q.default.green(`\u2705 ${A} bot(s) automatically paired to OpenClaw.`)),Dn(),Et();return}}catch{}await new Promise(a=>setTimeout(a,Ts))}n.fail(Q.default.red("Authentication timed out. Please try again.")),process.exit(1)});var Hn=require("commander"),Qe=d(require("chalk")),Pt=d(require("fs")),Ee=d(require("os")),et=d(require("path")),Ze=require("child_process");M();fe();function Bs(){let e=process.platform;if(e==="darwin"){let t=et.default.join(Ee.default.homedir(),"Library","LaunchAgents","ai.badgerclaw.watch.plist");(0,Ze.spawnSync)("launchctl",["unload",t],{stdio:"ignore"});try{Pt.default.unlinkSync(t)}catch{}}else if(e==="linux"){(0,Ze.spawnSync)("systemctl",["--user","disable","--now","badgerclaw-watch.service"],{stdio:"ignore"});let t=et.default.join(Ee.default.homedir(),".config","systemd","user","badgerclaw-watch.service");try{Pt.default.unlinkSync(t)}catch{}(0,Ze.spawnSync)("systemctl",["--user","daemon-reload"],{stdio:"ignore"})}(0,Ze.spawnSync)("pkill",["-f","badgerclaw heartbeat"],{stdio:"ignore"})}function Un(e){try{return Pt.default.rmSync(e,{recursive:!0,force:!0}),!0}catch{return!1}}var Fn=new Hn.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=S();if(t)try{let a=He(t.access_token),{version:l}=we();await a.post("/api/v1/openclaw/register",{instance_id:t.instance_id,label:Ee.default.hostname(),version:l,online:!1})}catch{}if(Bs(),e.keepState){je(),console.log(Qe.default.green("Logged out \u2014 auth cleared. (state preserved with --keep-state)"));return}let o=et.default.join(Ee.default.homedir(),".badgerclaw"),n=Un(o),r=et.default.join(Ee.default.homedir(),".openclaw","badgerclaw"),s=Un(r);n||s?(console.log(Qe.default.green("Logged out \u2014 local state cleared.")),console.log(Qe.default.dim(` Removed: ${o}${s?`, ${r}`:""}`))):console.log(Qe.default.green("Logged out."))});var Gn=require("commander"),bo=d(require("chalk"));M();var Wn=new Gn.Command("status").description("Show connected instance info").action(async()=>{let e=S();(!e||!ct())&&(console.log(bo.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(bo.default.green("Authenticated")),console.log(` User: ${lt(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var De=require("commander"),b=d(require("chalk")),Tt=d(require("ora")),Nt=d(require("fs")),zn=d(require("os")),Xn=d(require("path")),Qn=require("child_process");M();fe();var Pe=d(require("fs")),Vn=d(require("os")),qn=d(require("path")),Kn=require("child_process");Fe();function Dt(e){let t=e.split(":")[0].replace(/^@/,"").replace(/_bot$/,""),o=qn.join(Vn.homedir(),".openclaw","openclaw.json");return Pe.existsSync(o)?{changed:ye(()=>{let r=JSON.parse(Pe.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(l=>l.id!==t),r.agents.list.length!==a&&(s=!0)}return s&&Pe.writeFileSync(o,JSON.stringify(r,null,2)),s})}:{changed:!1}}function Ot(){try{return(0,Kn.execSync)("openclaw gateway restart",{stdio:"ignore"}),!0}catch{return!1}}be();function Jn(e){return e.hermes?"hermes":"openclaw"}function Yn(e){return e.openclaw.installed?"openclaw":e.hermes.installed?"hermes":"openclaw"}function So(){ct()||(console.log(b.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function js(e){return/^[a-z0-9_]{4,20}$/.test(e)}function Zn(e){return e.replace(/_bot$/,"")}var _o=["openclaw","hermes"],Ms=new De.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").option("-r, --runtime <runtime>",`Bot runtime: ${_o.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)=>{So(),js(e)||(console.log(b.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let o=t.runtime??Yn(ce());_o.includes(o)||(console.log(b.default.red(`Invalid --runtime "${t.runtime}". Must be one of: ${_o.join(", ")}.`)),process.exit(1));let n=(0,Tt.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(b.default.green(`Bot "${e}" (${o}) created successfully!`)),o==="hermes"&&console.log(b.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(b.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),Us=new De.Command("list").description("List your bots").action(async()=>{So();let e=(0,Tt.default)("Fetching bots...").start();try{let n=(await O().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),n.length===0){console.log(b.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(b.default.green(`Your bots (${n.length}):
125
+ `));for(let r of n){let s=Zn(r.username||r.name),a=r.active===!1?b.default.dim("deactivated"):r.openclaw_connected?b.default.green("connected"):b.default.gray("disconnected");console.log(` ${b.default.bold(s)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(b.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),Hs=new De.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{So();let t=(0,Tt.default)(`Deactivating bot "${e}"...`).start();try{await O().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(b.default.green(`Bot "${e}" deactivated.`));let{changed:n}=Dt(e);n&&(console.log(b.default.dim(" Removed from openclaw.json")),Ot()&&console.log(b.default.dim(" Gateway restarted")))}catch(o){let n=o.response?.data?.errors?.[0]||o.message;t.fail(b.default.red(`Failed to deactivate bot: ${n}`)),process.exit(1)}});function Fs(e){let t=e.trim();return t.startsWith("@")&&(t=t.slice(1)),t.includes(":")&&(t=t.split(":")[0]),Zn(t)}function Gs(e){let t=e.replace(/[^a-zA-Z0-9_.-]/g,"_")||"default";return Xn.default.join(zn.default.homedir(),".openclaw","badgerclaw","quarantine",`${t}.json`)}var Ws=new De.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=Fs(e);t||(console.log(b.default.red(`Couldn't parse bot name "${e}".`)),process.exit(1));let o=Gs(t),n=!1;if(Nt.default.existsSync(o))try{let r=JSON.parse(Nt.default.readFileSync(o,"utf-8")),s=r.failureCount??"?",a=r.quarantinedAt??"?";console.log(b.default.dim(` Quarantine for "${t}" \u2014 ${s} failures, since ${a}`)),Nt.default.unlinkSync(o),n=!0}catch(r){console.log(b.default.red(`Failed to clear quarantine ledger at ${o}: ${r.message}`)),process.exit(1)}console.log(n?b.default.green(`\u2705 Cleared quarantine for "${t}"`):b.default.dim(` No quarantine file for "${t}" \u2014 already healthy or never quarantined.`)),console.log(b.default.dim(" Restarting OpenClaw gateway so the refresh chain runs..."));try{(0,Qn.execSync)("openclaw gateway restart",{stdio:"inherit"})}catch(r){console.log(b.default.yellow(` Gateway restart command failed: ${r.message}`)),console.log(b.default.yellow(" Run `openclaw gateway restart` manually.")),process.exit(1)}console.log(b.default.green(`
126
+ \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(b.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(b.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(b.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(b.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),er=new De.Command("bot").description("Manage bots").addCommand(Ms).addCommand(Us).addCommand(Hs).addCommand(Ws);Ke();var pr=require("commander"),y=d(require("chalk"));M();se();Ke();de();ot();No();fe();Ce();var mr=3e3,ka=6e4,va=2700*1e3,gr=new pr.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{S()||(console.log(y.default.yellow("Not logged in.")),process.exit(1)),await qe(!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=S();a||(console.log(y.default.red(" Auth missing \u2014 run `badgerclaw login` and re-start `badgerclaw watch`.")),process.exit(1));let l=new t(`${U}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${a.access_token}`}});r=l,l.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")),l.close(),s()},va)},l.onerror=()=>{l.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,ka)},l.onmessage=async c=>{try{let i=JSON.parse(c.data);if(i.type==="pair"){let m=i.target_instance_id;if(m&&m!==Y()){console.log(y.default.dim(`
127
+ \u{1F4F1} Pair event for ${i.bot_name} targets ${m} \u2014 not us, skipping`));return}console.log(y.default.cyan(`
128
+ \u{1F4F1} Pair event received: ${i.bot_name}`)),await Ve(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(`
129
+ \u{1F504} Remote gateway-restart command received`));let m=await Ae();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(`
130
+ ${P} Bot ${p}: ${m} \u2014 removing from OpenClaw config...`));try{let{changed:f}=Dt(m);f?(console.log(y.default.green(" \u2705 Removed from openclaw.json")),Ot()?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(f){console.log(y.default.red(` Failed to update openclaw.json: ${f}`))}}else if(i.type==="claude_code.start"&&i.bot_id&&i.room_id){console.log(y.default.cyan(`
131
+ \u{1F916} Claude Code START received: bot=${i.bot_id} room=${i.room_id}`));try{let m=await ne({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 O().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(`
132
+ \u{1F916} Claude Code STOP received: bot=${i.bot_id} room=${i.room_id}`));try{let m=await ne({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 O().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(`
133
+ \u26A1 SSE command received: ${i.command_type} (${i.command_id})`));try{let m=O();await m.post(`/api/v1/dashboard/commands/${i.command_id}/ack`);let p=await ne({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 Rr=require("commander"),u=d(require("chalk")),Z=require("child_process"),I=d(require("fs")),rt=d(require("os")),re=d(require("path"));se();Re();be();var Ne=require("child_process"),hr=d(require("fs")),D=d(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 $a(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 yr(e,t,o=8e3){return(0,Ne.spawnSync)(e,t,{encoding:"utf-8",timeout:o})}function Lo(){let e=yr("docker",["version","--format","{{.Server.Version}}"],4e3);return e.status===0&&!!(e.stdout||"").trim()}function Ca(){return yr("docker",["--version"],4e3).status===0}function Oe(e){return(0,Ne.spawnSync)("sh",["-c",`command -v ${e}`],{encoding:"utf-8"}).status===0}function Ia(){return Oe("apt-get")?"apt":Oe("dnf")?"dnf":Oe("yum")?"yum":null}function Ra(){let e=(0,Ne.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 xa(){return process.platform==="darwin"?"darwin":process.platform==="linux"?Ra()?"linux-systemd":"linux-nosystemd":"unsupported"}function Aa(){return typeof process.getuid=="function"?process.getuid()===0:!1}function me(e,t){return t(D.default.dim(` $ ${e}`)),(0,Ne.spawnSync)("sh",["-c",e],{stdio:"inherit"}).status===0}function Ea(e,t,o){let n=t?"sudo ":"";switch(e.via){case"brew":return o(D.default.dim(" Installing colima + docker CLI via Homebrew...")),me("brew install colima docker",o);case"apt":return o(D.default.dim(" Installing Docker via apt...")),me(`${n}apt-get update`,o),me(`${n}apt-get install -y docker.io`,o);default:return!1}}function Pa(e,t,o){let n=t?"sudo ":"";switch(e){case"docker-app":return me("open -a Docker",o);case"colima":return me("colima start",o);case"systemctl":return me(`${n}systemctl enable --now docker`,o);case"dockerd-restricted":{if(!Oe("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&&!me("sudo -v",o))return o(D.default.red(" \u274C root is required to start dockerd here, but sudo is unavailable.")),!1;me(`${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,Ne.spawnSync)("sh",["-c",a],{stdio:"ignore"}).status===0}}}async function Da(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 wr(e={}){let t=e.log??(a=>console.log(a));if(process.env.BADGERCLAW_NO_AUTO_DEPS==="1"){let a=Lo();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:Lo(),binaryPresent:Ca(),host:xa(),hasBrew:Oe("brew"),hasDockerApp:hr.default.existsSync("/Applications/Docker.app"),hasColima:Oe("colima"),pkgManager:Ia(),isRoot:Aa()},n=$a(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&&!Ea(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}):Pa(n.start,r,t)?(t(D.default.dim(" Waiting for the Docker daemon to answer...")),await Da(Lo,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 br(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 _r(e=process.versions.node){return parseInt(String(e).split(".")[0],10)}var Bo=require("child_process"),Ft=d(require("fs")),Sr=d(require("os")),Gt=d(require("path"));be();kt();function Oa(){let e=kr();for(let t of e)if(Ft.default.existsSync(t))return t;return null}function kr(){return[Gt.default.resolve(__dirname,"..","assets","hermes-agent-bc.Dockerfile"),Gt.default.resolve(__dirname,"..","..","assets","hermes-agent-bc.Dockerfile")]}var Na="nousresearch/hermes-agent";function Ta(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`${Na}:${o}`}var La={run:e=>{let t=(0,Bo.spawnSync)("docker",e,{encoding:"utf-8"});return{status:t.status,stdout:t.stdout||"",stderr:t.stderr||""}}};function Ba(e){return["build",...e.hostNetwork?["--network","host"]:[],...e.upstreamRef?["--build-arg",`UPSTREAM=${e.upstreamRef}`]:[],"-t",e.image,"-f",e.dockerfile,e.ctxDir]}function vr(e){let t=ht();if(!t.installed)return{status:"no-docker"};let o=process.env.HERMES_IMAGE||xe;if(yt(t).installed)return{status:"already-present",image:o};let r=Oa();if(!r)return{status:"no-dockerfile",expectedPaths:kr()};let s=Ta(e),a=ao({bridgeUsable:()=>St(La)}),l=Ft.default.mkdtempSync(Gt.default.join(Sr.default.tmpdir(),"bc-hermes-build-"));try{let c=(0,Bo.spawnSync)("docker",Ba({hostNetwork:a,upstreamRef:s,image:o,dockerfile:r,ctxDir:l}),{stdio:"inherit",timeout:6e5});return c.status===0?{status:"built",image:o}:{status:"build-failed",image:o,stderr:`docker build exited ${c.status??"<no-status>"}`}}finally{try{Ft.default.rmSync(l,{recursive:!0,force:!0})}catch{}}}var q=re.default.join(rt.default.homedir(),".openclaw","openclaw.json"),nt=q+".badgerclaw-stash",xr=re.default.join(rt.default.homedir(),".openclaw","npm"),ja=re.default.join(xr,"package.json");async function $r(){try{let e=await fetch(`${U}/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 Ma(){if(!I.default.existsSync(q))return null;try{let e=JSON.parse(I.default.readFileSync(q,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,I.default.writeFileSync(q,JSON.stringify(e,null,2)),I.default.writeFileSync(nt,JSON.stringify(t,null,2)),t):null}catch{return null}}function Ua(){if(!I.default.existsSync(q))return null;try{let e=JSON.parse(I.default.readFileSync(q,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function Ha(e){if(e&&I.default.existsSync(q))try{let t=JSON.parse(I.default.readFileSync(q,"utf-8"));t.gateway={...e,...t.gateway||{}},I.default.writeFileSync(q,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 Fa(){if(I.default.existsSync(nt))try{let e=JSON.parse(I.default.readFileSync(nt,"utf-8")),t=JSON.parse(I.default.readFileSync(q,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,I.default.writeFileSync(q,JSON.stringify(t,null,2)),I.default.unlinkSync(nt)}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: ${nt}`))}}async function Cr(e){return new Promise(t=>{let o=(0,Z.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/,l=()=>{r||s||(r=!0,setTimeout(()=>{if(!s){try{o.kill("SIGTERM")}catch{}setTimeout(()=>{if(!s)try{o.kill("SIGKILL")}catch{}},1e3)}},3e3))},c=(i,m)=>{m.write(i),n+=i.toString("utf-8"),a.test(n)&&l()};o.stdout.on("data",i=>c(i,process.stdout)),o.stderr.on("data",i=>c(i,process.stderr)),o.on("exit",i=>{s=!0,t({status:r?0:i??1})}),o.on("error",i=>{s||(s=!0,console.error(u.default.red(` openclaw spawn error: ${i.message}`)),t({status:1}))})})}function Ir(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)+`
134
+ `),!0):!1}function Ga(){let e=[];Ir(ja)&&e.push(xr);for(let t of gt())Ir(re.default.join(t,"package.json"))&&e.push(t);return e}async function Wa(){let{detectCapabilities:e}=await Promise.resolve().then(()=>(be(),pn)),{pushHeartbeat:t}=await Promise.resolve().then(()=>(ot(),ur));console.log(u.default.green(`
135
135
  \u{1F9A1} BadgerClaw \u2014 capability refresh
136
- `));let o=e();console.log(m.default.dim(" Detected on this host:")),console.log(m.default.dim(` OpenClaw : ${Ao(o.openclaw)}`)),console.log(m.default.dim(` Hermes : ${Ao(o.hermes)}`)),console.log(m.default.dim(` Docker : ${Ao(o.docker)}`)),o.disk_free_gb!==null&&console.log(m.default.dim(` Disk free: ${o.disk_free_gb} GB`));try{await t(),console.log(m.default.green(`
137
- \u2705 Capabilities pushed to the API.`)),console.log(m.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(m.default.yellow(`
138
- \u26A0\uFE0F Not logged in \u2014 capabilities re-scanned locally but not posted to the API.`)),console.log(m.default.dim(" Run `badgerclaw login` first, then re-run `badgerclaw setup --refresh`."));return}console.log(m.default.red(`
139
- \u274C Failed to push capabilities: ${r}`)),process.exit(1)}}function Ao(e){return e.installed?e.version?`installed (${e.version})`:e.image?`installed (${e.image})`:"installed":"not installed"}var fr=new pr.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 ba();return}if(console.log(m.default.green(`
136
+ `));let o=e();console.log(u.default.dim(" Detected on this host:")),console.log(u.default.dim(` OpenClaw : ${jo(o.openclaw)}`)),console.log(u.default.dim(` Hermes : ${jo(o.hermes)}`)),console.log(u.default.dim(` Docker : ${jo(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(`
137
+ \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(`
138
+ \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(`
139
+ \u274C Failed to push capabilities: ${r}`)),process.exit(1)}}function jo(e){return e.installed?e.version?`installed (${e.version})`:e.image?`installed (${e.image})`:"installed":"not installed"}var Ar=new Rr.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 Wa();return}if(console.log(u.default.green(`
140
140
  \u{1F9A1} BadgerClaw Setup
141
- `)),Mn({hermes:e.hermes})==="hermes"){let f=fe();if(console.log(m.default.dim(` Detected: Docker ${f.docker.installed?"running":"not running"}, Hermes image ${f.hermes.installed?"present":"absent"}.`)),console.log(m.default.dim(` Selected runtime: ${m.default.cyan("hermes")} (via --hermes flag)
142
- `)),f.docker.installed||(console.log(m.default.red("\u274C Docker is not running \u2014 required for the Hermes runtime.")),console.log(m.default.dim(" Install Docker Desktop (or colima on macOS / docker-ce on Linux) and start it,")),console.log(m.default.dim(" then re-run `badgerclaw setup --hermes`.")),process.exit(1)),f.hermes.installed)console.log(m.default.dim(` Hermes image already present: ${f.hermes.image}`));else{let v=(await dr()).hermes;v&&console.log(m.default.dim(` Pinned Hermes upstream: ${v}`)),console.log(m.default.dim(" Building Hermes image (one-time, ~2 min)..."));let C=lr({upstream:v});C.status==="built"?console.log(m.default.green(` \u2705 Hermes image built: ${C.image}`)):C.status==="already-present"?console.log(m.default.dim(` Hermes image already present: ${C.image}`)):C.status==="no-dockerfile"?(console.log(m.default.red(`
143
- \u274C Bundled Hermes Dockerfile missing from CLI install.`)),console.log(m.default.dim(" Reinstall: npm install -g badgerclaw@latest")),console.log(m.default.dim(` Looked at: ${C.expectedPaths.join(", ")}`)),process.exit(1)):C.status==="build-failed"?(console.log(m.default.red(`
144
- \u274C Hermes image build failed: ${C.stderr}`)),console.log(m.default.dim(" See the docker output above for details.")),process.exit(1)):C.status==="no-docker"&&(console.log(m.default.red(`
145
- \u274C Docker is not running.`)),process.exit(1))}console.log(m.default.dim(`
141
+ `)),Jn({hermes:e.hermes})==="hermes"){let f=br({nodeMajor:_r(),npmPresent:(0,Z.spawnSync)("sh",["-c","command -v npm"],{encoding:"utf-8"}).status===0});f&&(console.log(u.default.red(`
142
+ \u274C ${f}`)),process.exit(1));let w=ce();if(console.log(u.default.dim(` Detected: Docker ${w.docker.installed?"running":"not running"}, Hermes image ${w.hermes.installed?"present":"absent"}.`)),console.log(u.default.dim(` Selected runtime: ${u.default.cyan("hermes")} (via --hermes flag)
143
+ `)),!w.docker.installed){console.log(u.default.dim(" Docker is not ready \u2014 bootstrapping it for the Hermes runtime..."));let A=await wr({log:$=>console.log($)});A.ok||(console.log(u.default.red(`
144
+ \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)),A.networkHostRequired&&console.log(u.default.dim(" \u24D8 No Docker bridge on this host \u2014 Hermes bots will use host networking automatically at pair time.")),w=ce()}if(w.disk_free_gb!==null&&w.disk_free_gb<6&&console.log(u.default.yellow(` \u26A0\uFE0F Low disk: ${w.disk_free_gb} GB free \u2014 the Hermes image build needs ~5 GB and may fail if it runs out.`)),w.hermes.installed)console.log(u.default.dim(` Hermes image already present: ${w.hermes.image}`));else{let A=(await $r()).hermes;A&&console.log(u.default.dim(` Pinned Hermes upstream: ${A}`)),console.log(u.default.dim(" Building Hermes image (one-time, ~2 min)..."));let $=vr({upstream:A});$.status==="built"?console.log(u.default.green(` \u2705 Hermes image built: ${$.image}`)):$.status==="already-present"?console.log(u.default.dim(` Hermes image already present: ${$.image}`)):$.status==="no-dockerfile"?(console.log(u.default.red(`
145
+ \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: ${$.expectedPaths.join(", ")}`)),process.exit(1)):$.status==="build-failed"?(console.log(u.default.red(`
146
+ \u274C Hermes image build failed: ${$.stderr}`)),console.log(u.default.dim(" See the docker output above for details.")),process.exit(1)):$.status==="no-docker"&&(console.log(u.default.red(`
147
+ \u274C Docker is not running.`)),process.exit(1))}console.log(u.default.dim(`
146
148
  Hermes-only mode \u2014 skipping OpenClaw plugin + gateway install.
147
149
  To enable OC bots later, drop the --hermes flag: \`badgerclaw setup\`.
148
- `)),console.log(m.default.green("\u2705 Setup complete (Hermes-only host).")),console.log(m.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 dr();if(o.cli){let f=qt();f!==o.cli?(console.log(m.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(m.default.red("\n\u274C CLI update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(m.default.green(` \u2705 CLI updated to ${o.cli}`))):console.log(m.default.dim(` CLI already at approved version ${f}.`))}if(o.openclaw){let f=F();f!==o.openclaw?(console.log(f===null?m.default.dim(` Installing OpenClaw ${o.openclaw} (supported)...`):m.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(m.default.red("\n\u274C OpenClaw install/update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(m.default.green(` \u2705 OpenClaw at ${o.openclaw}`))):console.log(m.default.dim(` OpenClaw already at approved version ${f}.`))}else F()===null&&(console.log(m.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(m.default.red(`
149
- \u274C OpenClaw install failed.`)),process.exit(1)));let n=ga();n&&console.log(m.default.dim(" Existing bot config stashed temporarily..."));let r=fa();(0,te.spawnSync)("openclaw",["gateway","stop"],{stdio:"pipe",shell:!0,timeout:1e4});let s=[oe.default.join(Ze.default.homedir(),".openclaw","extensions","badgerclaw"),oe.default.join(Ze.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),...lt()],a=[],l=[],c=f=>{let v=`${f}.bc-setup-stash-${Date.now()}-${Math.floor(Math.random()*1e6)}`,C=(0,te.spawnSync)("mv",["-f",f,v],{encoding:"utf-8"});return C.status===0?{ok:!0,stash:v}:{ok:!1,error:(C.stderr||"").trim()||`exit ${C.status}`}};for(let f of s)if(k.default.existsSync(f))try{k.default.rmSync(f,{recursive:!0,force:!0}),a.push(f)}catch(v){let C=c(f);C.ok?(l.push(`${f} \u2192 ${C.stash}`),console.log(m.default.yellow(` \u26A0\uFE0F Could not delete ${f} (${v.message}); renamed it aside instead.`))):(console.log(m.default.red(` \u274C Could not delete ${f} (${v.message})`)),console.log(m.default.red(` Could not rename ${f} aside either (${C.error}). Plugin install will likely fail.`)))}a.length>0&&console.log(m.default.dim(` Cleared existing plugin director${a.length>1?"ies":"y"}.`)),l.length>0&&console.log(m.default.dim(` Renamed busy install${l.length>1?"s":""} aside: ${l.join(", ")}`));let i=o.plugin?`@badgerclaw/connect@${o.plugin}`:"@badgerclaw/connect";o.plugin?console.log(m.default.dim(` Installing ${i} (supported)...`)):console.log(m.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let u=await ur(i);if(u.status===0&&o.plugin&&o.plugin!=="unknown"){for(let v=1;v<=2&&!(dt()===o.plugin||(console.log(m.default.yellow(` Plugin landed as a hook-pack-only install (not yet visible to \`badgerclaw login\`) \u2014 re-running plugin install (attempt ${v}/2)...`)),u=await ur(i),u.status!==0));v++);u.status===0&&dt()!==o.plugin&&console.log(m.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&&(ya(),console.log(m.default.dim(" Bot config restored."))),r&&(ha(r),console.log(m.default.dim(" Gateway config restored."))),u.status!==0&&(console.log(m.default.red(`
150
- \u274C Plugin install failed. Your bot config has been restored.`)),process.exit(1)),console.log(m.default.green(`
151
- \u2705 BadgerClaw plugin installed successfully!`));let p=wa();for(let f of p){console.log(m.default.dim(` Stripping OpenClaw uuid:14 override in ${f} (breaks request@2.88 in matrix-bot-sdk)...`));try{k.default.rmSync(oe.default.join(f,"node_modules","uuid"),{recursive:!0,force:!0})}catch{}try{k.default.rmSync(oe.default.join(f,"package-lock.json"),{force:!0})}catch{}(0,te.spawnSync)("npm",["install"],{cwd:f,stdio:"inherit",shell:!0}).status!==0&&(console.log(m.default.red(`
152
- \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(m.default.green(" \u2705 uuid override stripped + npm tree re-resolved.")),console.log("");let E=await St({verbose:!0});E.ok||(console.log(m.default.red(`
153
- \u274C Gateway failed to start. Diagnose with:`)),console.log(m.default.dim(" systemctl --user status openclaw-gateway.service # Linux")),console.log(m.default.dim(" launchctl list | grep openclaw # macOS")),console.log(m.default.dim(" openclaw config get gateway.mode")),console.log(m.default.dim(" Then re-run `badgerclaw setup` after fixing the underlying issue.")),process.exit(1)),E.ready===!1?console.log(m.default.yellow(" \u23F3 Gateway started but not answering yet \u2014 it may still be coming up.")):console.log(m.default.green(" \u2705 Gateway is running.")),console.log(m.default.dim("\nNext: run `badgerclaw login` to authenticate.")),$t()});Xe();var yr=require("commander"),R=d(require("chalk"));j();$e();ie();var wr=new yr.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{_()||(console.log(R.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=ge(),o=st(),n=await Ke();console.log(R.default.bold.green(`
150
+ `)),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 $r();if(o.cli){let f=to();f!==o.cli?(console.log(u.default.dim(` Updating CLI: ${f} \u2192 ${o.cli} (supported)...`)),(0,Z.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=W();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,Z.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 W()===null&&(console.log(u.default.yellow(" \u26A0\uFE0F No approved OpenClaw version and none installed \u2014 installing latest from npm.")),(0,Z.spawnSync)("npm",["install","-g","openclaw"],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red(`
151
+ \u274C OpenClaw install failed.`)),process.exit(1)));let n=Ma();n&&console.log(u.default.dim(" Existing bot config stashed temporarily..."));let r=Ua();(0,Z.spawnSync)("openclaw",["gateway","stop"],{stdio:"pipe",shell:!0,timeout:1e4});let s=[re.default.join(rt.default.homedir(),".openclaw","extensions","badgerclaw"),re.default.join(rt.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),...gt()],a=[],l=[],c=f=>{let w=`${f}.bc-setup-stash-${Date.now()}-${Math.floor(Math.random()*1e6)}`,A=(0,Z.spawnSync)("mv",["-f",f,w],{encoding:"utf-8"});return A.status===0?{ok:!0,stash:w}:{ok:!1,error:(A.stderr||"").trim()||`exit ${A.status}`}};for(let f of s)if(I.default.existsSync(f))try{I.default.rmSync(f,{recursive:!0,force:!0}),a.push(f)}catch(w){let A=c(f);A.ok?(l.push(`${f} \u2192 ${A.stash}`),console.log(u.default.yellow(` \u26A0\uFE0F Could not delete ${f} (${w.message}); renamed it aside instead.`))):(console.log(u.default.red(` \u274C Could not delete ${f} (${w.message})`)),console.log(u.default.red(` Could not rename ${f} aside either (${A.error}). Plugin install will likely fail.`)))}a.length>0&&console.log(u.default.dim(` Cleared existing plugin director${a.length>1?"ies":"y"}.`)),l.length>0&&console.log(u.default.dim(` Renamed busy install${l.length>1?"s":""} aside: ${l.join(", ")}`));let i=o.plugin?`@badgerclaw/connect@${o.plugin}`:"@badgerclaw/connect";o.plugin?console.log(u.default.dim(` Installing ${i} (supported)...`)):console.log(u.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let m=await Cr(i);if(m.status===0&&o.plugin&&o.plugin!=="unknown"){for(let w=1;w<=2&&!(ft()===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 ${w}/2)...`)),m=await Cr(i),m.status!==0));w++);m.status===0&&ft()!==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&&(Fa(),console.log(u.default.dim(" Bot config restored."))),r&&(Ha(r),console.log(u.default.dim(" Gateway config restored."))),m.status!==0&&(console.log(u.default.red(`
152
+ \u274C Plugin install failed. Your bot config has been restored.`)),process.exit(1)),console.log(u.default.green(`
153
+ \u2705 BadgerClaw plugin installed successfully!`));let p=Ga();for(let f of p){console.log(u.default.dim(` Stripping OpenClaw uuid:14 override in ${f} (breaks request@2.88 in matrix-bot-sdk)...`));try{I.default.rmSync(re.default.join(f,"node_modules","uuid"),{recursive:!0,force:!0})}catch{}try{I.default.rmSync(re.default.join(f,"package-lock.json"),{force:!0})}catch{}(0,Z.spawnSync)("npm",["install"],{cwd:f,stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red(`
154
+ \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(u.default.green(" \u2705 uuid override stripped + npm tree re-resolved.")),console.log("");let P=await At({verbose:!0});P.ok||(console.log(u.default.red(`
155
+ \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)),P.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.")),Et()});ot();var Pr=require("commander"),x=d(require("chalk"));M();Ce();de();var Dr=new Pr.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{S()||(console.log(x.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=we(),o=dt(),n=await Xe();console.log(x.default.bold.green(`
154
156
  BadgerClaw Dashboard
155
- `)),console.log(R.default.bold(" Instance")),console.log(` ID: ${q()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${n.pluginVersion}`),console.log(),console.log(R.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${hr(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let r=n.status==="running"?R.default.green:n.status==="error"?R.default.red:R.default.yellow;if(console.log(R.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(R.default.bold(" Bots")),console.log(R.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log(R.default.bold(` Bots (${n.bots.length})`)),console.log();for(let s of n.bots){let a=s.status==="running"?R.default.green:s.status==="error"?R.default.red:R.default.yellow;if(console.log(` ${R.default.bold(s.botUsername)} ${a(`[${s.status}]`)}`),console.log(` ID: ${s.botId}`),console.log(` Uptime: ${hr(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: ${R.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(R.default.dim(" Rooms:"));for(let l of s.roomDetails)console.log(R.default.dim(` ${l.roomName} \u2014 ${l.messagesInRoom} msgs, last: ${l.lastActivityInRoom??"N/A"}`))}console.log()}}console.log(R.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function hr(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 Eo=require("commander"),Ee=d(require("chalk")),br=d(require("ora"));j();ie();Xe();var _a=new Eo.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{_()||(console.log(Ee.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,br.default)("Restarting gateway...").start(),o=await ke();if(o.success){t.succeed(Ee.default.green(`Gateway restarted: ${o.message}`));try{await D(),console.log(Ee.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(Ee.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(Ee.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),_r=new Eo.Command("gateway").description("Manage the OpenClaw gateway").addCommand(_a);var de=require("commander"),b=d(require("chalk")),Se=d(require("ora")),le=d(require("axios"));Et();j();var _e="http://localhost:7331",Sa=new de.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(b.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,Se.default)("Starting Claude Code session...").start();try{await le.default.post(`${_e}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),s.text="Gateway toggled \u2014 launching MCP server...";let l=_o({sessionId:o,port:n,projectDir:r}).pid||0;await new Promise(c=>setTimeout(c,1500)),s.text="MCP server running \u2014 launching Claude Code...",So({sessionId:o,port:n,projectDir:r}),$o(o,0,l,n,r),s.succeed(b.default.green("Claude Code session started")+b.default.dim(` (session: ${o}, port: ${n})`)),console.log(b.default.dim(` Bot: ${e.bot}`)),console.log(b.default.dim(` Room: ${e.room}`)),console.log(b.default.dim(` Project: ${r}`)),console.log(b.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let l=a.response?.data?.message||a.message||"Unknown error";s.fail(b.default.red(`Failed to start Claude Code: ${l}`)),process.exit(1)}}),$a=new de.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(b.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,Se.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await le.default.post(`${_e}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let n=e.sessionId;if(!n)try{let a=((await le.default.get(`${_e}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(l=>l.botId===e.bot&&l.roomId===e.room);a&&(n=a.sessionId)}catch{}n?(vo(n),o.succeed(b.default.green(`Claude Code session stopped (${n})`))):(o.succeed(b.default.green("Claude Code toggled off at gateway")),console.log(b.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(b.default.red(`Failed to stop Claude Code: ${r}`)),process.exit(1)}}),va=new de.Command("status").description("Show active Claude Code sessions").action(async()=>{_()||(console.log(b.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,Se.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await le.default.get(`${_e}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let n=Co();if(t.stop(),o.length===0&&n.length===0){console.log(b.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(b.default.bold(`
156
- Gateway Claude Code Rooms:`)),console.log(b.default.dim(" Bot".padEnd(30)+"Room".padEnd(30)+"Session".padEnd(20)+"Enabled")),console.log(b.default.dim(" "+"-".repeat(88)));for(let r of o){let s=r.enabled?b.default.green("ON"):b.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(b.default.bold(`
157
- Local Sessions:`)),console.log(b.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(b.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(b.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),Ca=new de.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,Se.default)("Grouping bot+room into session...").start();try{await le.default.post(`${_e}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:e.session},{timeout:1e4}),t.succeed(b.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(b.default.red(`Failed to group: ${n}`)),process.exit(1)}}),Ia=new de.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,Se.default)("Adding user to allowlist...").start();try{await le.default.post(`${_e}/claude-code/allow`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(b.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(b.default.red(`Failed to add user: ${n}`)),process.exit(1)}}),ka=new de.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,Se.default)("Removing user from allowlist...").start();try{await le.default.post(`${_e}/claude-code/revoke`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(b.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(b.default.red(`Failed to revoke user: ${n}`)),process.exit(1)}}),Sr=new de.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(Sa).addCommand($a).addCommand(va).addCommand(Ca).addCommand(Ia).addCommand(ka);Ce();async function xa(){await Qo(process.argv);let e=new $r.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.61"),e.addCommand(En),e.addCommand(Dn),e.addCommand(Ln),e.addCommand(Wn),e.addCommand(hn),e.addCommand(sr),e.addCommand(fr),e.addCommand(Ro),e.addCommand(wr),e.addCommand(_r),e.addCommand(Sr),e.parse(process.argv)}xa().catch(e=>{console.error(e),process.exit(1)});
157
+ `)),console.log(x.default.bold(" Instance")),console.log(` ID: ${Y()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${n.pluginVersion}`),console.log(),console.log(x.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${Er(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let r=n.status==="running"?x.default.green:n.status==="error"?x.default.red:x.default.yellow;if(console.log(x.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(x.default.bold(" Bots")),console.log(x.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log(x.default.bold(` Bots (${n.bots.length})`)),console.log();for(let s of n.bots){let a=s.status==="running"?x.default.green:s.status==="error"?x.default.red:x.default.yellow;if(console.log(` ${x.default.bold(s.botUsername)} ${a(`[${s.status}]`)}`),console.log(` ID: ${s.botId}`),console.log(` Uptime: ${Er(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: ${x.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(x.default.dim(" Rooms:"));for(let l of s.roomDetails)console.log(x.default.dim(` ${l.roomName} \u2014 ${l.messagesInRoom} msgs, last: ${l.lastActivityInRoom??"N/A"}`))}console.log()}}console.log(x.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function Er(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 Mo=require("commander"),Te=d(require("chalk")),Or=d(require("ora"));M();de();ot();var Va=new Mo.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{S()||(console.log(Te.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,Or.default)("Restarting gateway...").start(),o=await Ae();if(o.success){t.succeed(Te.default.green(`Gateway restarted: ${o.message}`));try{await T(),console.log(Te.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(Te.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(Te.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),Nr=new Mo.Command("gateway").description("Manage the OpenClaw gateway").addCommand(Va);var ge=require("commander"),_=d(require("chalk")),$e=d(require("ora")),pe=d(require("axios"));jt();M();var ve="http://localhost:7331",qa=new ge.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=>{S()||(console.log(_.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,$e.default)("Starting Claude Code session...").start();try{await pe.default.post(`${ve}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),s.text="Gateway toggled \u2014 launching MCP server...";let l=Ro({sessionId:o,port:n,projectDir:r}).pid||0;await new Promise(c=>setTimeout(c,1500)),s.text="MCP server running \u2014 launching Claude Code...",xo({sessionId:o,port:n,projectDir:r}),Ao(o,0,l,n,r),s.succeed(_.default.green("Claude Code session started")+_.default.dim(` (session: ${o}, port: ${n})`)),console.log(_.default.dim(` Bot: ${e.bot}`)),console.log(_.default.dim(` Room: ${e.room}`)),console.log(_.default.dim(` Project: ${r}`)),console.log(_.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let l=a.response?.data?.message||a.message||"Unknown error";s.fail(_.default.red(`Failed to start Claude Code: ${l}`)),process.exit(1)}}),Ka=new ge.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=>{S()||(console.log(_.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,$e.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await pe.default.post(`${ve}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let n=e.sessionId;if(!n)try{let a=((await pe.default.get(`${ve}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(l=>l.botId===e.bot&&l.roomId===e.room);a&&(n=a.sessionId)}catch{}n?(Eo(n),o.succeed(_.default.green(`Claude Code session stopped (${n})`))):(o.succeed(_.default.green("Claude Code toggled off at gateway")),console.log(_.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(_.default.red(`Failed to stop Claude Code: ${r}`)),process.exit(1)}}),Ja=new ge.Command("status").description("Show active Claude Code sessions").action(async()=>{S()||(console.log(_.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,$e.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await pe.default.get(`${ve}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let n=Po();if(t.stop(),o.length===0&&n.length===0){console.log(_.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(_.default.bold(`
158
+ Gateway Claude Code Rooms:`)),console.log(_.default.dim(" Bot".padEnd(30)+"Room".padEnd(30)+"Session".padEnd(20)+"Enabled")),console.log(_.default.dim(" "+"-".repeat(88)));for(let r of o){let s=r.enabled?_.default.green("ON"):_.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(_.default.bold(`
159
+ Local Sessions:`)),console.log(_.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(_.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(_.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),Ya=new ge.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,$e.default)("Grouping bot+room into session...").start();try{await pe.default.post(`${ve}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:e.session},{timeout:1e4}),t.succeed(_.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(_.default.red(`Failed to group: ${n}`)),process.exit(1)}}),za=new ge.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,$e.default)("Adding user to allowlist...").start();try{await pe.default.post(`${ve}/claude-code/allow`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(_.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(_.default.red(`Failed to add user: ${n}`)),process.exit(1)}}),Xa=new ge.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,$e.default)("Removing user from allowlist...").start();try{await pe.default.post(`${ve}/claude-code/revoke`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(_.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(_.default.red(`Failed to revoke user: ${n}`)),process.exit(1)}}),Tr=new ge.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(qa).addCommand(Ka).addCommand(Ja).addCommand(Ya).addCommand(za).addCommand(Xa);Re();async function Qa(){await cn(process.argv);let e=new Lr.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.64"),e.addCommand(Mn),e.addCommand(Fn),e.addCommand(Wn),e.addCommand(er),e.addCommand(Cn),e.addCommand(gr),e.addCommand(Ar),e.addCommand(To),e.addCommand(Dr),e.addCommand(Nr),e.addCommand(Tr),e.parse(process.argv)}Qa().catch(e=>{console.error(e),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "name": "badgerclaw",
3
- "version": "0.2.61",
3
+ "version": "0.2.64",
4
+ "engines": {
5
+ "node": ">=18"
6
+ },
4
7
  "description": "BadgerClaw CLI — one-click bot provisioning",
5
8
  "main": "dist/index.js",
6
9
  "bin": {