badgerclaw 0.2.51 → 0.2.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +25 -25
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,20 +1,20 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var ar=Object.create;var Ke=Object.defineProperty;var ir=Object.getOwnPropertyDescriptor;var cr=Object.getOwnPropertyNames;var lr=Object.getPrototypeOf,dr=Object.prototype.hasOwnProperty;var T=(e,t)=>()=>(e&&(t=e(e=0)),t);var ur=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),vt=(e,t)=>{for(var o in t)Ke(e,o,{get:t[o],enumerable:!0})},yo=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of cr(t))!dr.call(e,r)&&r!==o&&Ke(e,r,{get:()=>t[r],enumerable:!(n=ir(t,r))||n.enumerable});return e};var i=(e,t,o)=>(o=e!=null?ar(lr(e)):{},yo(t||!e||!e.__esModule?Ke(o,"default",{value:e,enumerable:!0}):o,e)),_o=e=>yo(Ke({},"__esModule",{value:!0}),e);function y(){try{let e=Ie.default.readFileSync(xt,"utf-8");return JSON.parse(e)}catch{return null}}function Je(e){Ie.default.mkdirSync(Co,{recursive:!0}),Ie.default.writeFileSync(xt,JSON.stringify(e,null,2),{mode:384})}function ke(){try{Ie.default.unlinkSync(xt)}catch{}}function Ye(){let e=y();return e?new Date(e.expires_at)>new Date:!1}function ze(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var Ie,kt,$o,Co,xt,L=T(()=>{"use strict";Ie=i(require("fs")),kt=i(require("path")),$o=i(require("os")),Co=kt.default.join($o.default.homedir(),".badgerclaw"),xt=kt.default.join(Co,"auth.json")});function At(){return vo.default.createHash("sha256").update(`${F.default.hostname()}-${F.default.platform()}-${F.default.arch()}`).digest("hex").slice(0,16)}function U(){let e=y();if(e?.instance_id)return e.instance_id;let t=At();return`openclaw-${F.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function Xe(){return{hostname:F.default.hostname(),os:F.default.platform(),arch:F.default.arch(),uptimeSeconds:Math.floor(F.default.uptime()),memFreeMb:Math.floor(F.default.freemem()/1024/1024)}}var F,vo,he=T(()=>{"use strict";F=i(require("os")),vo=i(require("crypto"));L()});var Io,N,ko,z=T(()=>{"use strict";Io=process.env.BADGERCLAW_ENV==="local",N=process.env.BADGERCLAW_API_URL??(Io?"http://localhost:8000":"https://api.badger.signout.io"),ko=process.env.BADGERCLAW_AUTH_URL??(Io?"http://localhost:5500":"https://badgerclaw.ai")});function Ao(){return xe}function mr(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 Rt(){let e=y();if(!e?.refresh_token||!e?.email)return xe=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=mr(e.access_token);try{let o=await Ae.default.post(`${Ze}/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 xe="server returned no access_token",null;let s=n.expires_in||3600,a=new Date(Date.now()+s*1e3).toISOString();return Je({...e,access_token:r,expires_at:a}),xe=null,r}catch(o){let n=o?.response?.status,r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";xe=n?`HTTP ${n}: ${r}`:`network error: ${r}`;let s=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(n===403&&xo.test(s))throw ke(),new we(s);return null}}function Et(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 Ro(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(xo.test(n))return ke(),Promise.reject(new we(n))}return Promise.reject(t)}),e}function Eo(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,Qe||(Qe=Rt().finally(()=>{Qe=null}));let n=await Qe;return n?(o.headers.Authorization=`Bearer ${n}`,e.request(o)):Promise.reject(t)}),e}function x(){let e=y(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=Ae.default.create({baseURL:Ze,headers:t});return Et(o),Eo(o),Ro(o),o}function Po(){return Et(Ae.default.create({baseURL:Ze,headers:{"Content-Type":"application/json"}}))}function Re(e){let t=Ae.default.create({baseURL:Ze,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return Et(t),Eo(t),Ro(t),t}var Ae,Ze,we,xo,Qe,xe,re=T(()=>{"use strict";Ae=i(require("axios"));L();z();Ze=N,we=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},xo=/account\s+has\s+been\s+(deleted|deactivated)/i,Qe=null,xe=null});function Lo(){try{let e=X.default.statSync(se);return Date.now()-e.mtimeMs>Do}catch{return!0}}function Pt(){try{return X.default.mkdirSync(Ot.default.dirname(se),{recursive:!0}),X.default.writeFileSync(se,String(process.pid),{flag:"wx"}),!0}catch{if(Lo())try{return X.default.unlinkSync(se),X.default.writeFileSync(se,String(process.pid),{flag:"wx"}),!0}catch{return!1}return!1}}function No(){try{X.default.unlinkSync(se)}catch{}}async function jo(e){let t=!1;for(let o=0;o<pr;o++){if(Pt()){t=!0;break}await new Promise(n=>setTimeout(n,To))}t||console.warn("[config-lock] Could not acquire lock after timeout \u2014 proceeding without lock");try{return await e()}finally{t&&No()}}function ae(e){let t=Pt();if(!t&&Lo()){try{X.default.unlinkSync(se)}catch{}t=Pt()}try{return e()}finally{t&&No()}}var X,Oo,Ot,se,Do,To,pr,Ee=T(()=>{"use strict";X=i(require("fs")),Oo=i(require("os")),Ot=i(require("path")),se=Ot.default.join(Oo.default.homedir(),".openclaw","openclaw.json.lock"),Do=1e4,To=50,pr=Math.ceil(Do/To)});function tt(e){return H.default.join(gr,`bot-${e}`)}function Lt(e){return`badgerclaw-hermes-bot-${e}`}function Uo(){if(!P.default.existsSync(Dt))return{hermes_bots:{}};try{let e=P.default.readFileSync(Dt,"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 wr(e){P.default.existsSync(et)||P.default.mkdirSync(et,{recursive:!0,mode:448}),P.default.writeFileSync(Dt,JSON.stringify(e,null,2)+`
2
+ "use strict";var ar=Object.create;var Ke=Object.defineProperty;var ir=Object.getOwnPropertyDescriptor;var cr=Object.getOwnPropertyNames;var lr=Object.getPrototypeOf,dr=Object.prototype.hasOwnProperty;var T=(e,t)=>()=>(e&&(t=e(e=0)),t);var ur=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),vt=(e,t)=>{for(var o in t)Ke(e,o,{get:t[o],enumerable:!0})},yo=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of cr(t))!dr.call(e,r)&&r!==o&&Ke(e,r,{get:()=>t[r],enumerable:!(n=ir(t,r))||n.enumerable});return e};var c=(e,t,o)=>(o=e!=null?ar(lr(e)):{},yo(t||!e||!e.__esModule?Ke(o,"default",{value:e,enumerable:!0}):o,e)),_o=e=>yo(Ke({},"__esModule",{value:!0}),e);function y(){try{let e=Ie.default.readFileSync(xt,"utf-8");return JSON.parse(e)}catch{return null}}function Je(e){Ie.default.mkdirSync(Co,{recursive:!0}),Ie.default.writeFileSync(xt,JSON.stringify(e,null,2),{mode:384})}function ke(){try{Ie.default.unlinkSync(xt)}catch{}}function Ye(){let e=y();return e?new Date(e.expires_at)>new Date:!1}function ze(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var Ie,kt,$o,Co,xt,L=T(()=>{"use strict";Ie=c(require("fs")),kt=c(require("path")),$o=c(require("os")),Co=kt.default.join($o.default.homedir(),".badgerclaw"),xt=kt.default.join(Co,"auth.json")});function At(){return vo.default.createHash("sha256").update(`${U.default.hostname()}-${U.default.platform()}-${U.default.arch()}`).digest("hex").slice(0,16)}function F(){let e=y();if(e?.instance_id)return e.instance_id;let t=At();return`openclaw-${U.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function Xe(){return{hostname:U.default.hostname(),os:U.default.platform(),arch:U.default.arch(),uptimeSeconds:Math.floor(U.default.uptime()),memFreeMb:Math.floor(U.default.freemem()/1024/1024)}}var U,vo,he=T(()=>{"use strict";U=c(require("os")),vo=c(require("crypto"));L()});var Io,N,ko,z=T(()=>{"use strict";Io=process.env.BADGERCLAW_ENV==="local",N=process.env.BADGERCLAW_API_URL??(Io?"http://localhost:8000":"https://api.badger.signout.io"),ko=process.env.BADGERCLAW_AUTH_URL??(Io?"http://localhost:5500":"https://badgerclaw.ai")});function Ao(){return xe}function mr(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 Rt(){let e=y();if(!e?.refresh_token||!e?.email)return xe=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=mr(e.access_token);try{let o=await Ae.default.post(`${Ze}/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 xe="server returned no access_token",null;let s=n.expires_in||3600,a=new Date(Date.now()+s*1e3).toISOString();return Je({...e,access_token:r,expires_at:a}),xe=null,r}catch(o){let n=o?.response?.status,r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";xe=n?`HTTP ${n}: ${r}`:`network error: ${r}`;let s=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(n===403&&xo.test(s))throw ke(),new we(s);return null}}function Et(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 Ro(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(xo.test(n))return ke(),Promise.reject(new we(n))}return Promise.reject(t)}),e}function Eo(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,Qe||(Qe=Rt().finally(()=>{Qe=null}));let n=await Qe;return n?(o.headers.Authorization=`Bearer ${n}`,e.request(o)):Promise.reject(t)}),e}function x(){let e=y(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=Ae.default.create({baseURL:Ze,headers:t});return Et(o),Eo(o),Ro(o),o}function Po(){return Et(Ae.default.create({baseURL:Ze,headers:{"Content-Type":"application/json"}}))}function Re(e){let t=Ae.default.create({baseURL:Ze,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return Et(t),Eo(t),Ro(t),t}var Ae,Ze,we,xo,Qe,xe,re=T(()=>{"use strict";Ae=c(require("axios"));L();z();Ze=N,we=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},xo=/account\s+has\s+been\s+(deleted|deactivated)/i,Qe=null,xe=null});function Lo(){try{let e=X.default.statSync(se);return Date.now()-e.mtimeMs>Do}catch{return!0}}function Pt(){try{return X.default.mkdirSync(Ot.default.dirname(se),{recursive:!0}),X.default.writeFileSync(se,String(process.pid),{flag:"wx"}),!0}catch{if(Lo())try{return X.default.unlinkSync(se),X.default.writeFileSync(se,String(process.pid),{flag:"wx"}),!0}catch{return!1}return!1}}function No(){try{X.default.unlinkSync(se)}catch{}}async function jo(e){let t=!1;for(let o=0;o<pr;o++){if(Pt()){t=!0;break}await new Promise(n=>setTimeout(n,To))}t||console.warn("[config-lock] Could not acquire lock after timeout \u2014 proceeding without lock");try{return await e()}finally{t&&No()}}function ae(e){let t=Pt();if(!t&&Lo()){try{X.default.unlinkSync(se)}catch{}t=Pt()}try{return e()}finally{t&&No()}}var X,Oo,Ot,se,Do,To,pr,Ee=T(()=>{"use strict";X=c(require("fs")),Oo=c(require("os")),Ot=c(require("path")),se=Ot.default.join(Oo.default.homedir(),".openclaw","openclaw.json.lock"),Do=1e4,To=50,pr=Math.ceil(Do/To)});function tt(e){return H.default.join(gr,`bot-${e}`)}function Lt(e){return`badgerclaw-hermes-bot-${e}`}function Fo(){if(!P.default.existsSync(Dt))return{hermes_bots:{}};try{let e=P.default.readFileSync(Dt,"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 wr(e){P.default.existsSync(et)||P.default.mkdirSync(et,{recursive:!0,mode:448}),P.default.writeFileSync(Dt,JSON.stringify(e,null,2)+`
3
3
  `,{mode:384})}function yr(e,t=hr){let o=new Set(Object.values(e.hermes_bots).map(r=>r.port)),n=t;for(;o.has(n)||!_r(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 _r(e){let t=Mo.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 Go(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 br(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 Sr(e){switch(e){case"gemini":return"GOOGLE_API_KEY";case"anthropic":return"ANTHROPIC_API_KEY";case"openrouter":return"OPENROUTER_API_KEY"}}function $r(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(`${Sr(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}`),o.join(`
4
4
  `)+`
5
5
  `}function Cr(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: ${br(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(`
6
6
  `)}function vr(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(`
7
- `)}function Ir(e,t){let o=tt(e.botId);P.default.mkdirSync(o,{recursive:!0,mode:448});let n=H.default.join(o,".env"),r=H.default.join(o,"config.yaml"),s=H.default.join(o,"SOUL.md");return P.default.writeFileSync(n,$r(e,t),{mode:384}),P.default.writeFileSync(r,Cr(e),{mode:384}),P.default.existsSync(s)||P.default.writeFileSync(s,vr(e),{mode:384}),{dataDir:o,envPath:n,configPath:r,soulPath:s}}function kr(e){let t=process.getuid?.()??0,o=process.getgid?.()??0;return["run","-d","--name",e.containerName,"--restart","unless-stopped","-v",`${e.dataDir}:/opt/data`,"-p",`127.0.0.1:${e.port}:${e.port}`,"-e",`HERMES_UID=${t}`,"-e",`HERMES_GID=${o}`,"--env-file",`${e.dataDir}/.env`,e.image,"gateway","run"]}function Ho(e,t={}){let o=t.docker??Tt,n=e.image||process.env.HERMES_IMAGE||fr;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=Uo(),s=r.hermes_bots[e.botId],a=s?.port??yr(r,t.portBase),c=s?.container_name??Lt(e.botId);if(Ir(e,a),!t.skipDocker){o.run(["rm","-f",c]);let p=kr({containerName:c,dataDir:tt(e.botId),port:a,image:n}),g=o.run(p);if(g.status!==0)throw new Error(`docker run failed (exit ${g.status}): ${g.stderr||g.stdout}`)}let l={bot_id:e.botId,runtime:"hermes",container_name:c,port:a,data_dir:tt(e.botId),image:n,started_at:new Date().toISOString()};return r.hermes_bots[e.botId]=l,wr(r),l}function Vo(e={}){let t=e.docker??Tt,o=Uo(),n=[];for(let[r,s]of Object.entries(o.hermes_bots)){let a=t.run(["inspect","--format","{{.State.Status}}",s.container_name]),c,l=a.stdout.trim()||null;a.status!==0?(c="missing",l=(a.stderr||a.stdout).trim()||null):l==="running"?c="running":l==="exited"||l==="dead"||l==="created"?c="stopped":c="unknown",n.push({bot_id:r,container_name:s.container_name,status:c,raw:l})}return n}function Ar(e){let t=e.match(xr);return t?t[1].trim():null}async function Wo(e,t,o,n={}){let r={recoveryKey:null,posted:!1,envUpdated:!1};if(!e.backendBotId)return r;let a=(n.docker??Tt).run(["logs",t]),c=`${a.stdout}
8
- ${a.stderr}`,l=Ar(c);if(!l)return r;if(r.recoveryKey=l,n.api)try{let g=await n.api.post(`/api/v1/hermes/bots/${e.backendBotId}/runtime-bootstrap`,{recovery_key:l,image_ref:o});r.posted=g.status>=200&&g.status<300}catch(g){console.warn(`[hermes] failed to POST recovery key for ${e.botId}: ${g.message}. Daemon will retry next beat.`)}let p=n.envPath??H.default.join(tt(e.botId),".env");return P.default.existsSync(p)&&(P.default.readFileSync(p,"utf-8").includes("MATRIX_RECOVERY_KEY=")||(P.default.appendFileSync(p,`
7
+ `)}function Ir(e,t){let o=tt(e.botId);P.default.mkdirSync(o,{recursive:!0,mode:448});let n=H.default.join(o,".env"),r=H.default.join(o,"config.yaml"),s=H.default.join(o,"SOUL.md");return P.default.writeFileSync(n,$r(e,t),{mode:384}),P.default.writeFileSync(r,Cr(e),{mode:384}),P.default.existsSync(s)||P.default.writeFileSync(s,vr(e),{mode:384}),{dataDir:o,envPath:n,configPath:r,soulPath:s}}function kr(e){let t=process.getuid?.()??0,o=process.getgid?.()??0,n=["run","-d","--name",e.containerName,"--restart","unless-stopped","-v",`${e.dataDir}:/opt/data`,"-p",`127.0.0.1:${e.port}:${e.port}`];return 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 Ho(e,t={}){let o=t.docker??Tt,n=e.image||process.env.HERMES_IMAGE||fr;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=Fo(),s=r.hermes_bots[e.botId],a=s?.port??yr(r,t.portBase),l=s?.container_name??Lt(e.botId);if(Ir(e,a),!t.skipDocker){o.run(["rm","-f",l]);let p=kr({containerName:l,dataDir:tt(e.botId),port:a,image:n}),g=o.run(p);if(g.status!==0)throw new Error(`docker run failed (exit ${g.status}): ${g.stderr||g.stdout}`)}let i={bot_id:e.botId,runtime:"hermes",container_name:l,port:a,data_dir:tt(e.botId),image:n,started_at:new Date().toISOString()};return r.hermes_bots[e.botId]=i,wr(r),i}function Vo(e={}){let t=e.docker??Tt,o=Fo(),n=[];for(let[r,s]of Object.entries(o.hermes_bots)){let a=t.run(["inspect","--format","{{.State.Status}}",s.container_name]),l,i=a.stdout.trim()||null;a.status!==0?(l="missing",i=(a.stderr||a.stdout).trim()||null):i==="running"?l="running":i==="exited"||i==="dead"||i==="created"?l="stopped":l="unknown",n.push({bot_id:r,container_name:s.container_name,status:l,raw:i})}return n}function Ar(e){let t=e.match(xr);return t?t[1].trim():null}async function Wo(e,t,o,n={}){let r={recoveryKey:null,posted:!1,envUpdated:!1};if(!e.backendBotId)return r;let a=(n.docker??Tt).run(["logs",t]),l=`${a.stdout}
8
+ ${a.stderr}`,i=Ar(l);if(!i)return r;if(r.recoveryKey=i,n.api)try{let g=await n.api.post(`/api/v1/hermes/bots/${e.backendBotId}/runtime-bootstrap`,{recovery_key:i,image_ref:o});r.posted=g.status>=200&&g.status<300}catch(g){console.warn(`[hermes] failed to POST recovery key for ${e.botId}: ${g.message}. Daemon will retry next beat.`)}let p=n.envPath??H.default.join(tt(e.botId),".env");return P.default.existsSync(p)&&(P.default.readFileSync(p,"utf-8").includes("MATRIX_RECOVERY_KEY=")||(P.default.appendFileSync(p,`
9
9
  # Cross-signing recovery key captured from first-boot logs.
10
10
  # Hermes re-uses this on restart to re-sign the device after
11
11
  # Synapse rotates server keys.
12
- MATRIX_RECOVERY_KEY=${l}
13
- `),r.envUpdated=!0)),r}var Bo,P,Mo,Fo,H,et,gr,Dt,fr,hr,Tt,xr,Nt=T(()=>{"use strict";Bo=require("child_process"),P=i(require("fs")),Mo=i(require("net")),Fo=i(require("os")),H=i(require("path")),et=H.default.join(Fo.default.homedir(),".badgerclaw"),gr=H.default.join(et,"hermes"),Dt=H.default.join(et,"state.json"),fr="registry.getsignout.com/hermes-agent-bc:latest",hr=8642,Tt={run:e=>{let t=(0,Bo.spawnSync)("docker",e,{encoding:"utf-8"});return{status:t.status,stdout:t.stdout||"",stderr:t.stderr||""}}};xr=/SAVE THIS RECOVERY KEY[\s\S]*?key rotation:\s+((?:[A-Za-z0-9]{4}\s+){7,}[A-Za-z0-9]{4})/});function ot(e){return`'${e.replace(/'/g,"'\\''")}'`}function Rr(){if(Q!==null)return Q;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(Pe.default.existsSync(t))return Q=`${ot(process.execPath)} ${ot(t)}`,Q;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=Mt.default.join(o,"openclaw","openclaw.mjs");if(Pe.default.existsSync(n))return Q=`${ot(process.execPath)} ${ot(n)}`,Q}}catch{}return Q="openclaw",Q}function jt(e,t,o){t?t.fail(B.default.red(o)):e&&console.error(`[autopair] ${o}`)}async function Er(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={botId:e.user_id,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:Go()},o=Ho(t);if(t.backendBotId){let n=y();if(n){let r=Re(n.access_token);try{await Wo(t,Lt(t.botId),o.image,{api:{post:async(s,a)=>{let c=await r.post(s,a);return{status:c.status,data:c.data}}}})}catch(s){console.warn(`[hermes] recovery key capture failed for ${t.botId}: ${s.message}. Daemon will retry next beat.`)}}}}async function Oe(e,t,o,n){let r=y();if(!r)return;let s=n?null:(0,Bt.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${N}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e,instance_id:U()})});if(!a.ok){if(a.status===410){s?.info(B.default.dim(`${t} already paired (race-loss; another channel redeemed first).`));return}let g=await a.json().catch(()=>({errors:[a.statusText]}));jt(n,s,`Failed to redeem ${t}: ${g.errors?.[0]||a.status}`);return}let c=await a.json(),l=c.result??c;if((l.runtime??"openclaw")==="hermes"){try{await Er(l),s?.succeed(B.default.green(`\u2705 ${l.bot_name} (${l.user_id}) running on Hermes \u2014 bot is live!`))}catch(g){jt(n,s,`Failed to start Hermes container for ${t}: ${g.message}`)}return}await jo(async()=>{let g=l.user_id.split(":")[0].replace("@","").replace(/_bot$/,""),d;try{d=JSON.parse(Pe.default.readFileSync(qo,"utf-8"))}catch{d={}}d.channels||(d.channels={}),d.channels.badgerclaw||(d.channels.badgerclaw={}),d.channels.badgerclaw.accounts||(d.channels.badgerclaw.accounts={});let C={userId:l.user_id,accessToken:l.access_token,homeserver:l.homeserver,encryption:!0,groupPolicy:"open",allowlistOnly:!1,dm:{policy:"open"}};l.device_id&&(C.deviceId=l.device_id),d.channels.badgerclaw.accounts[g]=C,Pe.default.writeFileSync(qo,JSON.stringify(d,null,2),{mode:384})}),await fetch(`${N}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${r.access_token}`}}).catch(()=>{}),s?.succeed(B.default.green(`\u2705 ${l.bot_name} (${l.user_id}) paired \u2014 bot is live!`))}catch(a){jt(n,s,`Failed to pair ${t}: ${a.message}`)}}async function De(e=!1){let t=y();if(!t)return 0;let o=Re(t.access_token);try{let{data:n}=await o.get("/api/v1/openclaw/pending-pairs");if(!n||n.length===0)return 0;let r=new Map;for(let a of n)r.set(a.bot_user_id,a);for(let a of n)r.get(a.bot_user_id)!==a&&await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{});let s=0;for(let a of r.values()){let c=e?null:(0,Bt.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await Oe(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),s++}catch(l){c?.fail(B.default.red(`Error pairing ${a.bot_name}: ${l}`))}}if(s>0)try{let{execSync:a}=await import("child_process");a(`${Rr()} gateway restart`,{stdio:"ignore"}),e||console.log(B.default.green(`
12
+ MATRIX_RECOVERY_KEY=${i}
13
+ `),r.envUpdated=!0)),r}var Bo,P,Mo,Uo,H,et,gr,Dt,fr,hr,Tt,xr,Nt=T(()=>{"use strict";Bo=require("child_process"),P=c(require("fs")),Mo=c(require("net")),Uo=c(require("os")),H=c(require("path")),et=H.default.join(Uo.default.homedir(),".badgerclaw"),gr=H.default.join(et,"hermes"),Dt=H.default.join(et,"state.json"),fr="registry.getsignout.com/hermes-agent-bc:latest",hr=8642,Tt={run:e=>{let t=(0,Bo.spawnSync)("docker",e,{encoding:"utf-8"});return{status:t.status,stdout:t.stdout||"",stderr:t.stderr||""}}};xr=/SAVE THIS RECOVERY KEY[\s\S]*?key rotation:\s+((?:[A-Za-z0-9]{4}\s+){7,}[A-Za-z0-9]{4})/});function ot(e){return`'${e.replace(/'/g,"'\\''")}'`}function Rr(){if(Q!==null)return Q;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(Pe.default.existsSync(t))return Q=`${ot(process.execPath)} ${ot(t)}`,Q;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=Mt.default.join(o,"openclaw","openclaw.mjs");if(Pe.default.existsSync(n))return Q=`${ot(process.execPath)} ${ot(n)}`,Q}}catch{}return Q="openclaw",Q}function jt(e,t,o){t?t.fail(B.default.red(o)):e&&console.error(`[autopair] ${o}`)}async function Er(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:Go()},n=Ho(o);if(o.backendBotId){let r=y();if(r){let s=Re(r.access_token);try{await Wo(o,Lt(o.botId),n.image,{api:{post:async(a,l)=>{let i=await s.post(a,l);return{status:i.status,data:i.data}}}})}catch(a){console.warn(`[hermes] recovery key capture failed for ${o.botId}: ${a.message}. Daemon will retry next beat.`)}}}}async function Oe(e,t,o,n){let r=y();if(!r)return;let s=n?null:(0,Bt.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${N}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e,instance_id:F()})});if(!a.ok){if(a.status===410){s?.info(B.default.dim(`${t} already paired (race-loss; another channel redeemed first).`));return}let g=await a.json().catch(()=>({errors:[a.statusText]}));jt(n,s,`Failed to redeem ${t}: ${g.errors?.[0]||a.status}`);return}let l=await a.json(),i=l.result??l;if((i.runtime??"openclaw")==="hermes"){try{await Er(i),s?.succeed(B.default.green(`\u2705 ${i.bot_name} (${i.user_id}) running on Hermes \u2014 bot is live!`))}catch(g){jt(n,s,`Failed to start Hermes container for ${t}: ${g.message}`)}return}await jo(async()=>{let g=i.user_id.split(":")[0].replace("@","").replace(/_bot$/,""),d;try{d=JSON.parse(Pe.default.readFileSync(qo,"utf-8"))}catch{d={}}d.channels||(d.channels={}),d.channels.badgerclaw||(d.channels.badgerclaw={}),d.channels.badgerclaw.accounts||(d.channels.badgerclaw.accounts={});let C={userId:i.user_id,accessToken:i.access_token,homeserver:i.homeserver,encryption:!0,groupPolicy:"open",allowlistOnly:!1,dm:{policy:"open"}};i.device_id&&(C.deviceId=i.device_id),d.channels.badgerclaw.accounts[g]=C,Pe.default.writeFileSync(qo,JSON.stringify(d,null,2),{mode:384})}),await fetch(`${N}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${r.access_token}`}}).catch(()=>{}),s?.succeed(B.default.green(`\u2705 ${i.bot_name} (${i.user_id}) paired \u2014 bot is live!`))}catch(a){jt(n,s,`Failed to pair ${t}: ${a.message}`)}}async function De(e=!1){let t=y();if(!t)return 0;let o=Re(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,Bt.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await Oe(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),s++}catch(i){l?.fail(B.default.red(`Error pairing ${a.bot_name}: ${i}`))}}if(s>0)try{let{execSync:a}=await import("child_process");a(`${Rr()} gateway restart`,{stdio:"ignore"}),e||console.log(B.default.green(`
14
14
  \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(B.default.yellow(`
15
- \u26A1 ${s} bot(s) paired. Run: openclaw gateway restart`))}return s}catch{return 0}}var Ko,B,Bt,Jo,Mt,Pe,qo,Q,Yo,Te=T(()=>{"use strict";Ko=require("commander"),B=i(require("chalk")),Bt=i(require("ora")),Jo=i(require("os")),Mt=i(require("path")),Pe=i(require("fs"));L();re();z();he();Ee();Nt();qo=Mt.default.join(Jo.default.homedir(),".openclaw","openclaw.json");Q=null;Yo=new Ko.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!y()){console.log(B.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(B.default.dim("Checking for pending bot pairs...")),await De(!1)===0&&console.log(B.default.dim("No pending pairs found."))})});var le=ur((Na,Fr)=>{Fr.exports={name:"badgerclaw",version:"0.2.51",description:"BadgerClaw CLI \u2014 one-click bot provisioning",main:"dist/index.js",bin:{badgerclaw:"./dist/index.js"},files:["dist/","scripts/","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"}}});async function es(){try{return await pt.default.get(Zr,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function Ue(){try{let t=(await pt.default.get(`${vn}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(qt=t.pluginVersion),t}catch{return{status:await es()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:qt,bots:[]}}}function Kt(e){e&&e!=="unknown"&&(qt=e)}async function Se(){try{return{success:!0,message:(await pt.default.post(`${vn}/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 pt,Xr,vn,Qr,Zr,qt,de=T(()=>{"use strict";pt=i(require("axios")),Xr=7331,vn=`http://localhost:${Xr}`,Qr=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,Zr=`http://127.0.0.1:${Qr}`,qt="unknown"});function zt(){return"0.2.51"}function as(){for(let e of ss)try{let t=kn.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 is(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function Ce(){if((0,Jt.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,Jt.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:is(t.stdout)||null}async function cs(){let e=new AbortController,t=setTimeout(()=>e.abort(),os);try{let o=await fetch(ts,{signal:e.signal});if(!o.ok)return null;let n=await o.json(),r=n.result&&typeof n.result=="object"?n.result:n;return{cli:r.cli??"unknown",plugin:r.plugin??"unknown",supported_openclaw:r.supported_openclaw??"unknown"}}catch{return null}finally{clearTimeout(t)}}function ls(e){let t=[];if(e.cli&&e.cli!=="unknown"){let o=zt();o!==e.cli&&t.push({component:"cli",current:o,approved:e.cli})}if(e.plugin&&e.plugin!=="unknown"){let o=as();(o===null||o!==e.plugin)&&t.push({component:"plugin",current:o??"not installed",approved:e.plugin})}if(e.supported_openclaw&&e.supported_openclaw!=="unknown"){let o=Ce();(o===null||o!==e.supported_openclaw)&&t.push({component:"openclaw",current:o??"not installed",approved:e.supported_openclaw})}return t}function ds(e){return e[2]}function us(e){return!e||e.startsWith("-")?!0:ns.has(e)}function ms(e){let t=[];t.push(""),t.push(ee.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let n=o.component.padEnd(8);t.push(` ${n} ${ee.default.yellow(o.current)} \u2192 ${ee.default.green(o.approved)} ${ee.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(ee.default.green(" To fix, run:")),t.push(ee.default.green.bold(" badgerclaw setup")),t.push(""),t.push(ee.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
16
- `)}async function xn(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=ds(e);if(us(t))return;let o=await cs();if(!o)return;let n=ls(o);n.length!==0&&(process.stderr.write(ms(n)),process.exit(1))}var kn,Yt,$e,Jt,ee,ts,os,ns,In,rs,ss,gt=T(()=>{"use strict";kn=i(require("fs")),Yt=i(require("os")),$e=i(require("path")),Jt=require("child_process"),ee=i(require("chalk"));z();ts=`${N}/api/v1/dashboard/versions/latest`,os=2500,ns=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),In=$e.default.join(Yt.default.homedir(),".openclaw/extensions/badgerclaw"),rs=$e.default.join(Yt.default.homedir(),".openclaw/npm/node_modules/@badgerclaw/connect"),ss=[$e.default.join(rs,"package.json"),$e.default.join(In,"node_modules/@badgerclaw/connect/package.json"),$e.default.join(In,"package.json")]});var Tn={};vt(Tn,{detectCapabilities:()=>Qt,detectDiskFreeGb:()=>Dn,detectDocker:()=>En,detectHermes:()=>On,detectOpenClaw:()=>Pn});function En(){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 Pn(){let e=Ce();return e?{installed:!0,version:e}:{installed:!1}}function On(e){if(!e.installed)return{installed:!1};let t=process.env.HERMES_IMAGE||`${ps}:latest`;return(0,Ge.spawnSync)("docker",["image","inspect","--format","{{.RepoDigests}}",t],{encoding:"utf-8",timeout:3e3}).status!==0?{installed:!1}:{installed:!0,image:t}}function Dn(){let e=Rn.default.join(Xt.default.homedir(),".badgerclaw"),t=An.default.existsSync(e)?e:Xt.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(`
17
- `);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 Qt(){let e=En();return{openclaw:Pn(),hermes:On(e),docker:e,disk_free_gb:Dn(),ports_in_use:[]}}var Ge,An,Xt,Rn,ps,Zt=T(()=>{"use strict";Ge=require("child_process"),An=i(require("fs")),Xt=i(require("os")),Rn=i(require("path"));gt();ps="registry.getsignout.com/hermes-agent-bc"});var uo={};vt(uo,{getActiveSessions:()=>lo,launchClaudeCode:()=>ao,launchMCPServer:()=>so,recordSession:()=>io,stopSession:()=>co});function to(){try{if(O.default.existsSync(eo))return JSON.parse(O.default.readFileSync(eo,"utf-8"))}catch{}return[]}function oo(e){O.default.mkdirSync(ue,{recursive:!0}),O.default.writeFileSync(eo,JSON.stringify(e,null,2))}function ft(e){try{return process.kill(e,0),!0}catch{return!1}}function gs(){if(process.env.TMUX)return"tmux";try{if((0,q.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),O.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function no(e,t){let o=j.default.join(ue,`claude-launcher-${t}.exp`),n=j.default.join(ue,`pending-input-${t}.txt`);O.default.writeFileSync(n,"","utf-8");let r=`#!/usr/bin/expect -f
15
+ \u26A1 ${s} bot(s) paired. Run: openclaw gateway restart`))}return s}catch{return 0}}var Ko,B,Bt,Jo,Mt,Pe,qo,Q,Yo,Te=T(()=>{"use strict";Ko=require("commander"),B=c(require("chalk")),Bt=c(require("ora")),Jo=c(require("os")),Mt=c(require("path")),Pe=c(require("fs"));L();re();z();he();Ee();Nt();qo=Mt.default.join(Jo.default.homedir(),".openclaw","openclaw.json");Q=null;Yo=new Ko.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!y()){console.log(B.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(B.default.dim("Checking for pending bot pairs...")),await De(!1)===0&&console.log(B.default.dim("No pending pairs found."))})});var le=ur((Na,Ur)=>{Ur.exports={name:"badgerclaw",version:"0.2.52",description:"BadgerClaw CLI \u2014 one-click bot provisioning",main:"dist/index.js",bin:{badgerclaw:"./dist/index.js"},files:["dist/","scripts/","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"}}});async function es(){try{return await pt.default.get(Zr,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function Fe(){try{let t=(await pt.default.get(`${vn}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(qt=t.pluginVersion),t}catch{return{status:await es()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:qt,bots:[]}}}function Kt(e){e&&e!=="unknown"&&(qt=e)}async function Se(){try{return{success:!0,message:(await pt.default.post(`${vn}/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 pt,Xr,vn,Qr,Zr,qt,de=T(()=>{"use strict";pt=c(require("axios")),Xr=7331,vn=`http://localhost:${Xr}`,Qr=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,Zr=`http://127.0.0.1:${Qr}`,qt="unknown"});function zt(){return"0.2.52"}function as(){for(let e of ss)try{let t=kn.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 is(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function Ce(){if((0,Jt.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,Jt.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:is(t.stdout)||null}async function cs(){let e=new AbortController,t=setTimeout(()=>e.abort(),os);try{let o=await fetch(ts,{signal:e.signal});if(!o.ok)return null;let n=await o.json(),r=n.result&&typeof n.result=="object"?n.result:n;return{cli:r.cli??"unknown",plugin:r.plugin??"unknown",supported_openclaw:r.supported_openclaw??"unknown"}}catch{return null}finally{clearTimeout(t)}}function ls(e){let t=[];if(e.cli&&e.cli!=="unknown"){let o=zt();o!==e.cli&&t.push({component:"cli",current:o,approved:e.cli})}if(e.plugin&&e.plugin!=="unknown"){let o=as();(o===null||o!==e.plugin)&&t.push({component:"plugin",current:o??"not installed",approved:e.plugin})}if(e.supported_openclaw&&e.supported_openclaw!=="unknown"){let o=Ce();(o===null||o!==e.supported_openclaw)&&t.push({component:"openclaw",current:o??"not installed",approved:e.supported_openclaw})}return t}function ds(e){return e[2]}function us(e){return!e||e.startsWith("-")?!0:ns.has(e)}function ms(e){let t=[];t.push(""),t.push(ee.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let n=o.component.padEnd(8);t.push(` ${n} ${ee.default.yellow(o.current)} \u2192 ${ee.default.green(o.approved)} ${ee.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(ee.default.green(" To fix, run:")),t.push(ee.default.green.bold(" badgerclaw setup")),t.push(""),t.push(ee.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
16
+ `)}async function xn(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=ds(e);if(us(t))return;let o=await cs();if(!o)return;let n=ls(o);n.length!==0&&(process.stderr.write(ms(n)),process.exit(1))}var kn,Yt,$e,Jt,ee,ts,os,ns,In,rs,ss,gt=T(()=>{"use strict";kn=c(require("fs")),Yt=c(require("os")),$e=c(require("path")),Jt=require("child_process"),ee=c(require("chalk"));z();ts=`${N}/api/v1/dashboard/versions/latest`,os=2500,ns=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),In=$e.default.join(Yt.default.homedir(),".openclaw/extensions/badgerclaw"),rs=$e.default.join(Yt.default.homedir(),".openclaw/npm/node_modules/@badgerclaw/connect"),ss=[$e.default.join(rs,"package.json"),$e.default.join(In,"node_modules/@badgerclaw/connect/package.json"),$e.default.join(In,"package.json")]});var Tn={};vt(Tn,{detectCapabilities:()=>Qt,detectDiskFreeGb:()=>Dn,detectDocker:()=>En,detectHermes:()=>On,detectOpenClaw:()=>Pn});function En(){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 Pn(){let e=Ce();return e?{installed:!0,version:e}:{installed:!1}}function On(e){if(!e.installed)return{installed:!1};let t=process.env.HERMES_IMAGE||`${ps}:latest`;return(0,Ge.spawnSync)("docker",["image","inspect","--format","{{.RepoDigests}}",t],{encoding:"utf-8",timeout:3e3}).status!==0?{installed:!1}:{installed:!0,image:t}}function Dn(){let e=Rn.default.join(Xt.default.homedir(),".badgerclaw"),t=An.default.existsSync(e)?e:Xt.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(`
17
+ `);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 Qt(){let e=En();return{openclaw:Pn(),hermes:On(e),docker:e,disk_free_gb:Dn(),ports_in_use:[]}}var Ge,An,Xt,Rn,ps,Zt=T(()=>{"use strict";Ge=require("child_process"),An=c(require("fs")),Xt=c(require("os")),Rn=c(require("path"));gt();ps="registry.getsignout.com/hermes-agent-bc"});var uo={};vt(uo,{getActiveSessions:()=>lo,launchClaudeCode:()=>ao,launchMCPServer:()=>so,recordSession:()=>io,stopSession:()=>co});function to(){try{if(O.default.existsSync(eo))return JSON.parse(O.default.readFileSync(eo,"utf-8"))}catch{}return[]}function oo(e){O.default.mkdirSync(ue,{recursive:!0}),O.default.writeFileSync(eo,JSON.stringify(e,null,2))}function ft(e){try{return process.kill(e,0),!0}catch{return!1}}function gs(){if(process.env.TMUX)return"tmux";try{if((0,q.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),O.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function no(e,t){let o=j.default.join(ue,`claude-launcher-${t}.exp`),n=j.default.join(ue,`pending-input-${t}.txt`);O.default.writeFileSync(n,"","utf-8");let r=`#!/usr/bin/expect -f
18
18
  set timeout -1
19
19
  set msgfile "${n}"
20
20
 
@@ -64,8 +64,8 @@ interact timeout 2 {
64
64
  activate
65
65
  do script "${`cd ${ht(t)} && ${r} && ${ht(n)}`.replace(/"/g,'\\"')}"
66
66
  end tell
67
- `;(0,q.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function ws(e,t,o){let n=no(e,o.BADGERCLAW_SESSION_ID||"default"),r=ro(o),s=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${r} && ${n}`;(0,q.execSync)(`tmux new-session -d -s ${s} "${a}"`,{stdio:"pipe",timeout:1e4})}function ht(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function so(e){let t=j.default.join(__dirname,"..","claude-code","mcp-server.js"),o=O.default.existsSync(t)?t:j.default.join(__dirname,"mcp-server.js"),n=(0,q.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 ao(e){let t=j.default.join(j.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=j.default.join(__dirname,"..","claude-code","mcp-server.js"),n=j.default.join(__dirname,"mcp-server.js"),r=O.default.existsSync(t)?t:O.default.existsSync(o)?o:n,s={BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},a=JSON.stringify({mcpServers:{badgerclaw:{command:"node",args:[r],env:s}}}),c=j.default.join(ue,`mcp-config-${e.sessionId}.json`);O.default.mkdirSync(ue,{recursive:!0}),O.default.writeFileSync(c,a,"utf-8");let l=`claude --dangerously-skip-permissions --mcp-config ${c}`;switch(gs()){case"iterm2":fs(l,e.projectDir,s);break;case"terminal":hs(l,e.projectDir,s);break;case"tmux":ws(l,e.projectDir,s);break;case"direct":(0,q.spawn)(l,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...s},stdio:"ignore",detached:!0}).unref();break}}function io(e,t,o,n,r){let s=to().filter(a=>a.sessionId!==e);s.push({sessionId:e,pid:t,mcpPid:o,port:n,projectDir:r,startedAt:new Date().toISOString()}),oo(s)}function co(e){let t=to(),o=t.find(r=>r.sessionId===e);if(!o)return!1;if(o.mcpPid&&ft(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&ft(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,q.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let n=t.filter(r=>r.sessionId!==e);return oo(n),!0}function lo(){let e=to(),t=e.filter(o=>ft(o.mcpPid)||ft(o.pid));return t.length!==e.length&&oo(t),t}var q,O,j,Ln,ue,eo,wt=T(()=>{"use strict";q=require("child_process"),O=i(require("fs")),j=i(require("path")),Ln=i(require("os")),ue=j.default.join(Ln.default.homedir(),".badgerclaw"),eo=j.default.join(ue,"claude-sessions.json")});async function K(e){return e.command_type==="update_cli"?_s(e.payload?.target_version):e.command_type==="update_plugin"?bs(e.payload?.target_version):e.command_type==="restart_gateway"?ys():e.command_type==="leave_room"?Ts(e.payload):e.command_type==="start_claude_code"?Is(e.payload):e.command_type==="stop_claude_code"?ks(e.payload):e.command_type==="start_claude_control"?xs(e.payload):e.command_type==="stop_claude_control"?As(e.payload):e.command_type==="update_claude_tools"?Rs(e.payload):e.command_type==="bot_share_notify"?Es(e.payload):e.command_type==="bot_share_revoked"?Ps(e.payload):e.command_type==="bot_share_expired"?Os(e.payload):e.command_type==="bot_refresh"?Ds(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function ys(){try{return(0,I.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,I.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 _s(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,I.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,I.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),r=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return $s(),{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 bs(e){let t=b.default.join(me.default.homedir(),".openclaw","extensions","badgerclaw"),o=b.default.join(me.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),n=f.default.existsSync(o)?"npm":f.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 g=b.default.dirname(b.default.dirname(b.default.dirname(o)));(0,I.execSync)(`npm install ${r}`,{cwd:g,stdio:"pipe",timeout:12e4});let d=b.default.join(o,"package.json"),C="unknown";f.default.existsSync(d)&&(C=JSON.parse(f.default.readFileSync(d,"utf-8")).version||"unknown"),Kt(C);try{(0,I.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await Nn(C)}let s=t;(0,I.execSync)(`npm install ${r}`,{cwd:s,stdio:"pipe",timeout:12e4});let a=b.default.join(s,"node_modules","@badgerclaw","connect"),c=b.default.join(a,"package.json"),l="unknown";f.default.existsSync(c)&&(l=JSON.parse(f.default.readFileSync(c,"utf-8")).version||"unknown"),Kt(l),Ss(a,s);let p=b.default.join(s,"package.json");if(f.default.existsSync(p)&&f.default.existsSync(c))try{let g=JSON.parse(f.default.readFileSync(p,"utf-8")),d=JSON.parse(f.default.readFileSync(c,"utf-8"));g.version=l,d.openclaw&&(g.openclaw={...g.openclaw,...d.openclaw}),f.default.writeFileSync(p,JSON.stringify(g,null,2)+`
68
- `)}catch{}try{(0,I.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await Nn(l)}catch(s){return{success:!1,message:`Plugin update failed: ${(s.stderr?.toString()||s.message||"").slice(0,500)}`}}}async function Nn(e){for(let t=0;t<15;t++){await new Promise(o=>setTimeout(o,1e3));try{let o=await D.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 Ss(e,t){let o=b.default.join(e,"dist"),n=b.default.join(t,"dist");f.default.existsSync(o)&&(f.default.mkdirSync(n,{recursive:!0}),mo(o,n));let r=b.default.join(e,"openclaw.plugin.json");f.default.existsSync(r)&&f.default.copyFileSync(r,b.default.join(t,"openclaw.plugin.json"));let s=b.default.join(e,"scripts"),a=b.default.join(t,"scripts");f.default.existsSync(s)&&(f.default.mkdirSync(a,{recursive:!0}),mo(s,a));for(let c of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let l=b.default.join(t,c);f.default.existsSync(l)&&(f.default.statSync(l).isDirectory()?f.default.rmSync(l,{recursive:!0,force:!0}):f.default.unlinkSync(l))}}function mo(e,t){for(let o of f.default.readdirSync(e,{withFileTypes:!0})){let n=b.default.join(e,o.name),r=b.default.join(t,o.name);o.isDirectory()?(f.default.mkdirSync(r,{recursive:!0}),mo(n,r)):f.default.copyFileSync(n,r)}}function $s(){try{try{(0,I.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,I.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,I.execSync)("sleep 1",{stdio:"pipe"});let e=(0,I.execSync)("which badgerclaw",{stdio:"pipe"}).toString().trim();(0,I.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,I.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function Cs(){let e=b.default.join(me.default.homedir(),".badgerclaw","workspace");f.default.mkdirSync(e,{recursive:!0});let t=b.default.join(e,".git");return f.default.existsSync(t)||(0,I.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),f.default.writeFileSync(b.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
67
+ `;(0,q.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function ws(e,t,o){let n=no(e,o.BADGERCLAW_SESSION_ID||"default"),r=ro(o),s=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${r} && ${n}`;(0,q.execSync)(`tmux new-session -d -s ${s} "${a}"`,{stdio:"pipe",timeout:1e4})}function ht(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function so(e){let t=j.default.join(__dirname,"..","claude-code","mcp-server.js"),o=O.default.existsSync(t)?t:j.default.join(__dirname,"mcp-server.js"),n=(0,q.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 ao(e){let t=j.default.join(j.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=j.default.join(__dirname,"..","claude-code","mcp-server.js"),n=j.default.join(__dirname,"mcp-server.js"),r=O.default.existsSync(t)?t:O.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=j.default.join(ue,`mcp-config-${e.sessionId}.json`);O.default.mkdirSync(ue,{recursive:!0}),O.default.writeFileSync(l,a,"utf-8");let i=`claude --dangerously-skip-permissions --mcp-config ${l}`;switch(gs()){case"iterm2":fs(i,e.projectDir,s);break;case"terminal":hs(i,e.projectDir,s);break;case"tmux":ws(i,e.projectDir,s);break;case"direct":(0,q.spawn)(i,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...s},stdio:"ignore",detached:!0}).unref();break}}function io(e,t,o,n,r){let s=to().filter(a=>a.sessionId!==e);s.push({sessionId:e,pid:t,mcpPid:o,port:n,projectDir:r,startedAt:new Date().toISOString()}),oo(s)}function co(e){let t=to(),o=t.find(r=>r.sessionId===e);if(!o)return!1;if(o.mcpPid&&ft(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&ft(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,q.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let n=t.filter(r=>r.sessionId!==e);return oo(n),!0}function lo(){let e=to(),t=e.filter(o=>ft(o.mcpPid)||ft(o.pid));return t.length!==e.length&&oo(t),t}var q,O,j,Ln,ue,eo,wt=T(()=>{"use strict";q=require("child_process"),O=c(require("fs")),j=c(require("path")),Ln=c(require("os")),ue=j.default.join(Ln.default.homedir(),".badgerclaw"),eo=j.default.join(ue,"claude-sessions.json")});async function K(e){return e.command_type==="update_cli"?_s(e.payload?.target_version):e.command_type==="update_plugin"?bs(e.payload?.target_version):e.command_type==="restart_gateway"?ys():e.command_type==="leave_room"?Ts(e.payload):e.command_type==="start_claude_code"?Is(e.payload):e.command_type==="stop_claude_code"?ks(e.payload):e.command_type==="start_claude_control"?xs(e.payload):e.command_type==="stop_claude_control"?As(e.payload):e.command_type==="update_claude_tools"?Rs(e.payload):e.command_type==="bot_share_notify"?Es(e.payload):e.command_type==="bot_share_revoked"?Ps(e.payload):e.command_type==="bot_share_expired"?Os(e.payload):e.command_type==="bot_refresh"?Ds(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function ys(){try{return(0,I.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,I.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 _s(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,I.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,I.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),r=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return $s(),{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 bs(e){let t=b.default.join(me.default.homedir(),".openclaw","extensions","badgerclaw"),o=b.default.join(me.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),n=f.default.existsSync(o)?"npm":f.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 g=b.default.dirname(b.default.dirname(b.default.dirname(o)));(0,I.execSync)(`npm install ${r}`,{cwd:g,stdio:"pipe",timeout:12e4});let d=b.default.join(o,"package.json"),C="unknown";f.default.existsSync(d)&&(C=JSON.parse(f.default.readFileSync(d,"utf-8")).version||"unknown"),Kt(C);try{(0,I.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await Nn(C)}let s=t;(0,I.execSync)(`npm install ${r}`,{cwd:s,stdio:"pipe",timeout:12e4});let a=b.default.join(s,"node_modules","@badgerclaw","connect"),l=b.default.join(a,"package.json"),i="unknown";f.default.existsSync(l)&&(i=JSON.parse(f.default.readFileSync(l,"utf-8")).version||"unknown"),Kt(i),Ss(a,s);let p=b.default.join(s,"package.json");if(f.default.existsSync(p)&&f.default.existsSync(l))try{let g=JSON.parse(f.default.readFileSync(p,"utf-8")),d=JSON.parse(f.default.readFileSync(l,"utf-8"));g.version=i,d.openclaw&&(g.openclaw={...g.openclaw,...d.openclaw}),f.default.writeFileSync(p,JSON.stringify(g,null,2)+`
68
+ `)}catch{}try{(0,I.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await Nn(i)}catch(s){return{success:!1,message:`Plugin update failed: ${(s.stderr?.toString()||s.message||"").slice(0,500)}`}}}async function Nn(e){for(let t=0;t<15;t++){await new Promise(o=>setTimeout(o,1e3));try{let o=await D.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 Ss(e,t){let o=b.default.join(e,"dist"),n=b.default.join(t,"dist");f.default.existsSync(o)&&(f.default.mkdirSync(n,{recursive:!0}),mo(o,n));let r=b.default.join(e,"openclaw.plugin.json");f.default.existsSync(r)&&f.default.copyFileSync(r,b.default.join(t,"openclaw.plugin.json"));let s=b.default.join(e,"scripts"),a=b.default.join(t,"scripts");f.default.existsSync(s)&&(f.default.mkdirSync(a,{recursive:!0}),mo(s,a));for(let l of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let i=b.default.join(t,l);f.default.existsSync(i)&&(f.default.statSync(i).isDirectory()?f.default.rmSync(i,{recursive:!0,force:!0}):f.default.unlinkSync(i))}}function mo(e,t){for(let o of f.default.readdirSync(e,{withFileTypes:!0})){let n=b.default.join(e,o.name),r=b.default.join(t,o.name);o.isDirectory()?(f.default.mkdirSync(r,{recursive:!0}),mo(n,r)):f.default.copyFileSync(n,r)}}function $s(){try{try{(0,I.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,I.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,I.execSync)("sleep 1",{stdio:"pipe"});let e=(0,I.execSync)("which badgerclaw",{stdio:"pipe"}).toString().trim();(0,I.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,I.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function Cs(){let e=b.default.join(me.default.homedir(),".badgerclaw","workspace");f.default.mkdirSync(e,{recursive:!0});let t=b.default.join(e,".git");return f.default.existsSync(t)||(0,I.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),f.default.writeFileSync(b.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,9 +74,9 @@ 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 vs(){try{f.default.mkdirSync(b.default.dirname(yt),{recursive:!0});try{let e=f.default.statSync(yt);if(Date.now()-e.mtimeMs<6e4)return!1;f.default.unlinkSync(yt)}catch{}return f.default.writeFileSync(yt,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function Is(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!vs())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 He(e.bot_id),{launchClaudeCode:o,recordSession:n,getActiveSessions:r,stopSession:s}=(wt(),_o(uo)),a=new Set;try{let C=(await D.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let k of C)if(k.botId!==t&&k.enabled!==!1){let Y=k.port;typeof Y=="number"&&Y>=7332&&a.add(Y)}}catch{}for(let d=7332;d<=7340;d++)try{(0,I.execSync)(`lsof -ti :${d} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(d)}catch{}let c=7332;for(;a.has(c);)c++;let l=r();for(let d of l)d.port===c&&(console.log(`[command-executor] Stopping existing session ${d.sessionId} on port ${c}`),s(d.sessionId));try{(0,I.execSync)(`lsof -ti :${c} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let p=e.session_id||`session-${Date.now()}`;await D.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:p,port:c},{timeout:1e4});let g=Cs();return o({sessionId:p,port:c,projectDir:g}),n(p,0,0,c,g),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${p}, port: ${c})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function He(e){if(e.startsWith("@"))return e;try{let o=(await D.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],n=b.default.join(me.default.homedir(),".badgerclaw","bot-mapping.json");if(f.default.existsSync(n)){let r=JSON.parse(f.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 ks(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 He(e.bot_id),o=e.session_id;if(!o)try{let n=await D.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 D.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:n}=(wt(),_o(uo));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 xs(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 He(t));let n=e?.session_id||`cc-${Date.now()}`;return await D.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 As(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 He(t)),await D.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 Rs(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 He(t)),await D.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 Es(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 D.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 Ps(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 D.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 Os(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 D.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 Ds(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=b.default.join(me.default.homedir(),".openclaw","badgerclaw","quarantine",`${o}.json`);try{f.default.rmSync(n,{force:!0})}catch{}try{return(0,I.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 Ts(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 D.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 I,f,b,me,D,yt,po=T(()=>{"use strict";I=require("child_process"),f=i(require("fs")),b=i(require("path")),me=i(require("os")),D=i(require("axios"));de();yt=b.default.join(me.default.homedir(),".badgerclaw","claude-code.lock")});var Wn={};vt(Wn,{heartbeatCommand:()=>go,pushHeartbeat:()=>R});function bt(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 _t)n-s>Ms&&_t.delete(r);return _t.has(o)?!0:(_t.set(o,n),!1)}function Hn(e,t){let o=Xe();return{instance_id:U(),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:Qt(),hermes_containers:Vo(),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 R(){let{version:e}=le(),t=await Ue(),o=Hn(t,e);await x().post(Gn,o)}function Fs(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 Mn(){try{let o=(await x().get(js)).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 Un.default.post("http://localhost:7331/bot-share/sync",n,{timeout:1e4}),console.log(m.default.dim(` [${S()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(m.default.dim(` [${S()}] Share sync failed (non-fatal): ${e.message}`))}}async function Us(){if(!Bn){Bn=!0;try{await x().post(Ns,{instance_id:U()},{timeout:Bs}),console.log(m.default.dim(` [${new Date().toISOString()}] Posted disconnect \u2014 dashboard will mark machine offline immediately.`))}catch(e){console.log(m.default.dim(` [${new Date().toISOString()}] Disconnect post failed (non-fatal): ${e?.message||e}`))}}}async function Vn(){let e=y();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(m.default.dim(` [${S()}] Token expires soon \u2014 refreshing proactively...`)),await Rt())console.log(m.default.green(` [${S()}] Token refreshed successfully`));else{let s=Ao()||"unknown reason";console.log(m.default.yellow(` [${S()}] Token refresh failed: ${s}`))}}function Hs(e,t){let o=3e3,n=3e4,r=null;async function s(){try{await Vn();let c=y()?.access_token||e,l=require("eventsource"),p=new l(`${N}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${c}`}});p.onopen=()=>{o=3e3,console.log(m.default.dim(` [${S()}] SSE connected \u2014 listening for real-time events`)),r&&clearTimeout(r),r=setTimeout(()=>{console.log(m.default.dim(` [${S()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),p.close(),s()},Gs)},p.onmessage=async g=>{try{let d=JSON.parse(g.data);await Vs(d)}catch{}},p.onerror=async()=>{p.close(),r&&(clearTimeout(r),r=null),console.log(m.default.dim(` [${S()}] SSE disconnected \u2014 reconnecting in ${o/1e3}s...`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}catch(a){console.log(m.default.dim(` [${S()}] SSE connection failed: ${a.message}`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}s()}function S(){return new Date().toISOString()}async function Vs(e){if(e.type==="pair"){console.log(m.default.cyan(` [${S()}] Pair event: ${e.bot_name}`)),await Oe(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(m.default.green(` [${S()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await R()}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(m.default.yellow(` [${S()}] 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(ae(()=>{let l=JSON.parse(n.readFileSync(a,"utf-8")),p=!1;if(l.channels?.badgerclaw?.accounts?.[o]&&(delete l.channels.badgerclaw.accounts[o],p=!0),l.agents?.list){let g=l.agents.list.length;l.agents.list=l.agents.list.filter(d=>d.id!==o),l.agents.list.length!==g&&(p=!0)}return p&&n.writeFileSync(a,JSON.stringify(l,null,2)),p})){console.log(m.default.green(` [${S()}] Removed "${o}" from openclaw.json`));let{execSync:l}=await import("child_process");try{l("openclaw gateway restart",{stdio:"ignore"}),console.log(m.default.green(` [${S()}] Gateway restarted`))}catch{}}}catch(n){console.log(m.default.red(` [${S()}] Failed to clean up bot: ${n}`))}try{await R()}catch{}}else if(e.type==="gateway-restart"){console.log(m.default.cyan(` [${S()}] Remote gateway-restart received`));let t=await Se();console.log(t.success?m.default.green(` [${S()}] Gateway restarted`):m.default.red(` [${S()}] Gateway restart failed: ${t.message}`));try{await R()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(m.default.cyan(` [${S()}] Claude Code START: bot=${e.bot_id}`)),bt("start_claude_code",e.bot_id)){console.log(m.default.dim(` [${S()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await K({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 x().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await R()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(m.default.cyan(` [${S()}] Claude Code STOP: bot=${e.bot_id}`)),bt("stop_claude_code",e.bot_id)){console.log(m.default.dim(` [${S()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await K({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 x().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await R()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(m.default.cyan(` [${S()}] Command: ${e.command_type} (${e.command_id})`)),bt(e.command_type,e.payload?.bot_id)){console.log(m.default.dim(` [${S()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=x();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await K({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(m.default.cyan(` [${S()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await R()}catch{}}}var Fn,m,Un,jn,Ls,Gn,Ns,js,Bs,Bn,_t,Ms,go,Gs,Ve=T(()=>{"use strict";Fn=require("commander"),m=i(require("chalk")),Un=i(require("axios"));L();re();he();Zt();Nt();de();po();z();Te();de();Ee();jn=3e4,Ls=15e4,Gn="/api/v1/dashboard/heartbeat",Ns="/api/v1/dashboard/disconnect",js="/api/v1/me/active-shares",Bs=3e3,Bn=!1,_t=new Map,Ms=3e4;go=new Fn.Command("heartbeat").description("Run heartbeat daemon \u2014 reports telemetry to the BadgerClaw dashboard every 30s").action(async()=>{let e=y();e||(console.log(m.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=le();console.log(m.default.green(`Heartbeat daemon started (v${t})`)),console.log(m.default.dim(` Instance: ${U()}`)),console.log(m.default.dim(` Interval: ${jn/1e3}s`)),console.log(m.default.dim(` Press Ctrl+C to stop.
78
- `));let o=null,n=10,r=0,s=async()=>{try{await Vn();let c=await Ue(),l=Hn(c,t);Fs(o,c)&&o!==null&&console.log(m.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let g=x(),d=await g.post(Gn,l);r=0;let C=c.bots.length,k=c.bots.filter(A=>A.status==="running").length;console.log(m.default.dim(` [${new Date().toISOString()}] gateway=${c.status} bots=${k}/${C} running mem=${l.mem_free_mb}MB free`)),o=c;let Y=d.data?.pending_commands||[],$t=!1;for(let A of Y)try{if(console.log(m.default.cyan(` [${new Date().toISOString()}] Received command: ${A.command_type} (${A.id})`)),await g.post(`/api/v1/dashboard/commands/${A.id}/ack`),bt(A.command_type,A.payload?.bot_id)){console.log(m.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${A.command_type}`));continue}let E=await K(A);console.log(E.success?m.default.green(` [${new Date().toISOString()}] ${E.message}`):m.default.red(` [${new Date().toISOString()}] ${E.message}`)),await g.post(`/api/v1/dashboard/commands/${A.id}/result`,{status:E.success?"success":"failed",result:E.message,new_version:E.newVersion||null}),A.command_type==="update_cli"&&E.success&&($t=!0)}catch(E){console.log(m.default.dim(` [${new Date().toISOString()}] Command ${A.id} error: ${E.message}`))}if($t){console.log(m.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await R()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(c){c instanceof we&&(console.log(m.default.yellow(` [${new Date().toISOString()}] Account deactivated \u2014 signed out. Exiting daemon.`)),process.exit(0)),r+=1,console.log(m.default.dim(` [${new Date().toISOString()}] Heartbeat failed (${r}/${n}): ${c.message}`)),r>=n&&(console.log(m.default.red(` [${new Date().toISOString()}] ${n} consecutive heartbeat failures \u2014 exiting so launchctl/systemd can restart the daemon.`)),process.exit(1))}};await s(),await Mn(),setInterval(s,jn),setInterval(Mn,Ls),Hs(e.access_token,t);let a=c=>{console.log(m.default.yellow(`
79
- [${new Date().toISOString()}] Received ${c} \u2014 posting disconnect and exiting.`)),Us().finally(()=>{process.exit(0)})};process.on("SIGTERM",a),process.on("SIGINT",a),await new Promise(()=>{})});Gs=2700*1e3});var or=require("commander");var an=require("commander"),Z=i(require("chalk")),cn=i(require("ora")),ln=i(require("open")),Ht=i(require("os"));var It=i(require("crypto"));function bo(){return It.default.randomBytes(32).toString("base64url")}function So(e){return It.default.createHash("sha256").update(e).digest("base64url")}L();he();re();z();Te();var tn=i(require("os"));var nt=i(require("fs")),ie=i(require("path")),Le=i(require("os")),Ne=require("child_process"),zo="ai.badgerclaw.watch",Xo=ie.default.join(Le.default.homedir(),"Library","LaunchAgents"),Ft=ie.default.join(Xo,`${zo}.plist`);function Pr(){try{return(0,Ne.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function Or(){try{return(0,Ne.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function Dr(e){let t=ie.default.join(Le.default.homedir(),".badgerclaw"),o=Or(),n=ie.default.dirname(o),r=ie.default.dirname(e),s=[n,r,"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"],a=new Set,c=s.filter(l=>!l||a.has(l)?!1:(a.add(l),!0)).join(":");return`<?xml version="1.0" encoding="UTF-8"?>
77
+ `),e}function vs(){try{f.default.mkdirSync(b.default.dirname(yt),{recursive:!0});try{let e=f.default.statSync(yt);if(Date.now()-e.mtimeMs<6e4)return!1;f.default.unlinkSync(yt)}catch{}return f.default.writeFileSync(yt,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function Is(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!vs())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 He(e.bot_id),{launchClaudeCode:o,recordSession:n,getActiveSessions:r,stopSession:s}=(wt(),_o(uo)),a=new Set;try{let C=(await D.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let k of C)if(k.botId!==t&&k.enabled!==!1){let Y=k.port;typeof Y=="number"&&Y>=7332&&a.add(Y)}}catch{}for(let d=7332;d<=7340;d++)try{(0,I.execSync)(`lsof -ti :${d} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(d)}catch{}let l=7332;for(;a.has(l);)l++;let i=r();for(let d of i)d.port===l&&(console.log(`[command-executor] Stopping existing session ${d.sessionId} on port ${l}`),s(d.sessionId));try{(0,I.execSync)(`lsof -ti :${l} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let p=e.session_id||`session-${Date.now()}`;await D.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:p,port:l},{timeout:1e4});let g=Cs();return o({sessionId:p,port:l,projectDir:g}),n(p,0,0,l,g),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${p}, port: ${l})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function He(e){if(e.startsWith("@"))return e;try{let o=(await D.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],n=b.default.join(me.default.homedir(),".badgerclaw","bot-mapping.json");if(f.default.existsSync(n)){let r=JSON.parse(f.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 ks(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 He(e.bot_id),o=e.session_id;if(!o)try{let n=await D.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 D.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:n}=(wt(),_o(uo));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 xs(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 He(t));let n=e?.session_id||`cc-${Date.now()}`;return await D.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 As(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 He(t)),await D.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 Rs(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 He(t)),await D.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 Es(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 D.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 Ps(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 D.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 Os(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 D.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 Ds(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=b.default.join(me.default.homedir(),".openclaw","badgerclaw","quarantine",`${o}.json`);try{f.default.rmSync(n,{force:!0})}catch{}try{return(0,I.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 Ts(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 D.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 I,f,b,me,D,yt,po=T(()=>{"use strict";I=require("child_process"),f=c(require("fs")),b=c(require("path")),me=c(require("os")),D=c(require("axios"));de();yt=b.default.join(me.default.homedir(),".badgerclaw","claude-code.lock")});var Wn={};vt(Wn,{heartbeatCommand:()=>go,pushHeartbeat:()=>R});function bt(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 _t)n-s>Ms&&_t.delete(r);return _t.has(o)?!0:(_t.set(o,n),!1)}function Hn(e,t){let o=Xe();return{instance_id:F(),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:Qt(),hermes_containers:Vo(),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 R(){let{version:e}=le(),t=await Fe(),o=Hn(t,e);await x().post(Gn,o)}function Us(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 Mn(){try{let o=(await x().get(js)).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 Fn.default.post("http://localhost:7331/bot-share/sync",n,{timeout:1e4}),console.log(m.default.dim(` [${S()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(m.default.dim(` [${S()}] Share sync failed (non-fatal): ${e.message}`))}}async function Fs(){if(!Bn){Bn=!0;try{await x().post(Ns,{instance_id:F()},{timeout:Bs}),console.log(m.default.dim(` [${new Date().toISOString()}] Posted disconnect \u2014 dashboard will mark machine offline immediately.`))}catch(e){console.log(m.default.dim(` [${new Date().toISOString()}] Disconnect post failed (non-fatal): ${e?.message||e}`))}}}async function Vn(){let e=y();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(m.default.dim(` [${S()}] Token expires soon \u2014 refreshing proactively...`)),await Rt())console.log(m.default.green(` [${S()}] Token refreshed successfully`));else{let s=Ao()||"unknown reason";console.log(m.default.yellow(` [${S()}] Token refresh failed: ${s}`))}}function Hs(e,t){let o=3e3,n=3e4,r=null;async function s(){try{await Vn();let l=y()?.access_token||e,i=require("eventsource"),p=new i(`${N}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${l}`}});p.onopen=()=>{o=3e3,console.log(m.default.dim(` [${S()}] SSE connected \u2014 listening for real-time events`)),r&&clearTimeout(r),r=setTimeout(()=>{console.log(m.default.dim(` [${S()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),p.close(),s()},Gs)},p.onmessage=async g=>{try{let d=JSON.parse(g.data);await Vs(d)}catch{}},p.onerror=async()=>{p.close(),r&&(clearTimeout(r),r=null),console.log(m.default.dim(` [${S()}] SSE disconnected \u2014 reconnecting in ${o/1e3}s...`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}catch(a){console.log(m.default.dim(` [${S()}] SSE connection failed: ${a.message}`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}s()}function S(){return new Date().toISOString()}async function Vs(e){if(e.type==="pair"){console.log(m.default.cyan(` [${S()}] Pair event: ${e.bot_name}`)),await Oe(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(m.default.green(` [${S()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await R()}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(m.default.yellow(` [${S()}] 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(ae(()=>{let i=JSON.parse(n.readFileSync(a,"utf-8")),p=!1;if(i.channels?.badgerclaw?.accounts?.[o]&&(delete i.channels.badgerclaw.accounts[o],p=!0),i.agents?.list){let g=i.agents.list.length;i.agents.list=i.agents.list.filter(d=>d.id!==o),i.agents.list.length!==g&&(p=!0)}return p&&n.writeFileSync(a,JSON.stringify(i,null,2)),p})){console.log(m.default.green(` [${S()}] Removed "${o}" from openclaw.json`));let{execSync:i}=await import("child_process");try{i("openclaw gateway restart",{stdio:"ignore"}),console.log(m.default.green(` [${S()}] Gateway restarted`))}catch{}}}catch(n){console.log(m.default.red(` [${S()}] Failed to clean up bot: ${n}`))}try{await R()}catch{}}else if(e.type==="gateway-restart"){console.log(m.default.cyan(` [${S()}] Remote gateway-restart received`));let t=await Se();console.log(t.success?m.default.green(` [${S()}] Gateway restarted`):m.default.red(` [${S()}] Gateway restart failed: ${t.message}`));try{await R()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(m.default.cyan(` [${S()}] Claude Code START: bot=${e.bot_id}`)),bt("start_claude_code",e.bot_id)){console.log(m.default.dim(` [${S()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await K({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 x().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await R()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(m.default.cyan(` [${S()}] Claude Code STOP: bot=${e.bot_id}`)),bt("stop_claude_code",e.bot_id)){console.log(m.default.dim(` [${S()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await K({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 x().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await R()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(m.default.cyan(` [${S()}] Command: ${e.command_type} (${e.command_id})`)),bt(e.command_type,e.payload?.bot_id)){console.log(m.default.dim(` [${S()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=x();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await K({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(m.default.cyan(` [${S()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await R()}catch{}}}var Un,m,Fn,jn,Ls,Gn,Ns,js,Bs,Bn,_t,Ms,go,Gs,Ve=T(()=>{"use strict";Un=require("commander"),m=c(require("chalk")),Fn=c(require("axios"));L();re();he();Zt();Nt();de();po();z();Te();de();Ee();jn=3e4,Ls=15e4,Gn="/api/v1/dashboard/heartbeat",Ns="/api/v1/dashboard/disconnect",js="/api/v1/me/active-shares",Bs=3e3,Bn=!1,_t=new Map,Ms=3e4;go=new Un.Command("heartbeat").description("Run heartbeat daemon \u2014 reports telemetry to the BadgerClaw dashboard every 30s").action(async()=>{let e=y();e||(console.log(m.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=le();console.log(m.default.green(`Heartbeat daemon started (v${t})`)),console.log(m.default.dim(` Instance: ${F()}`)),console.log(m.default.dim(` Interval: ${jn/1e3}s`)),console.log(m.default.dim(` Press Ctrl+C to stop.
78
+ `));let o=null,n=10,r=0,s=async()=>{try{await Vn();let l=await Fe(),i=Hn(l,t);Us(o,l)&&o!==null&&console.log(m.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let g=x(),d=await g.post(Gn,i);r=0;let C=l.bots.length,k=l.bots.filter(A=>A.status==="running").length;console.log(m.default.dim(` [${new Date().toISOString()}] gateway=${l.status} bots=${k}/${C} running mem=${i.mem_free_mb}MB free`)),o=l;let Y=d.data?.pending_commands||[],$t=!1;for(let A of Y)try{if(console.log(m.default.cyan(` [${new Date().toISOString()}] Received command: ${A.command_type} (${A.id})`)),await g.post(`/api/v1/dashboard/commands/${A.id}/ack`),bt(A.command_type,A.payload?.bot_id)){console.log(m.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${A.command_type}`));continue}let E=await K(A);console.log(E.success?m.default.green(` [${new Date().toISOString()}] ${E.message}`):m.default.red(` [${new Date().toISOString()}] ${E.message}`)),await g.post(`/api/v1/dashboard/commands/${A.id}/result`,{status:E.success?"success":"failed",result:E.message,new_version:E.newVersion||null}),A.command_type==="update_cli"&&E.success&&($t=!0)}catch(E){console.log(m.default.dim(` [${new Date().toISOString()}] Command ${A.id} error: ${E.message}`))}if($t){console.log(m.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await R()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(l){l instanceof we&&(console.log(m.default.yellow(` [${new Date().toISOString()}] Account deactivated \u2014 signed out. Exiting daemon.`)),process.exit(0)),r+=1,console.log(m.default.dim(` [${new Date().toISOString()}] Heartbeat failed (${r}/${n}): ${l.message}`)),r>=n&&(console.log(m.default.red(` [${new Date().toISOString()}] ${n} consecutive heartbeat failures \u2014 exiting so launchctl/systemd can restart the daemon.`)),process.exit(1))}};await s(),await Mn(),setInterval(s,jn),setInterval(Mn,Ls),Hs(e.access_token,t);let a=l=>{console.log(m.default.yellow(`
79
+ [${new Date().toISOString()}] Received ${l} \u2014 posting disconnect and exiting.`)),Fs().finally(()=>{process.exit(0)})};process.on("SIGTERM",a),process.on("SIGINT",a),await new Promise(()=>{})});Gs=2700*1e3});var or=require("commander");var an=require("commander"),Z=c(require("chalk")),cn=c(require("ora")),ln=c(require("open")),Ht=c(require("os"));var It=c(require("crypto"));function bo(){return It.default.randomBytes(32).toString("base64url")}function So(e){return It.default.createHash("sha256").update(e).digest("base64url")}L();he();re();z();Te();var tn=c(require("os"));var nt=c(require("fs")),ie=c(require("path")),Le=c(require("os")),Ne=require("child_process"),zo="ai.badgerclaw.watch",Xo=ie.default.join(Le.default.homedir(),"Library","LaunchAgents"),Ut=ie.default.join(Xo,`${zo}.plist`);function Pr(){try{return(0,Ne.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function Or(){try{return(0,Ne.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function Dr(e){let t=ie.default.join(Le.default.homedir(),".badgerclaw"),o=Or(),n=ie.default.dirname(o),r=ie.default.dirname(e),s=[n,r,"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"],a=new Set,l=s.filter(i=>!i||a.has(i)?!1:(a.add(i),!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>
@@ -91,7 +91,7 @@ Keep responses concise and helpful.
91
91
  <key>EnvironmentVariables</key>
92
92
  <dict>
93
93
  <key>PATH</key>
94
- <string>${c}</string>
94
+ <string>${l}</string>
95
95
  </dict>
96
96
  <key>RunAtLoad</key>
97
97
  <true/>
@@ -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 Qo(){if(Le.default.platform()==="darwin")try{let e=Pr();nt.default.mkdirSync(Xo,{recursive:!0}),nt.default.mkdirSync(ie.default.join(Le.default.homedir(),".badgerclaw"),{recursive:!0}),nt.default.writeFileSync(Ft,Dr(e));try{(0,Ne.execSync)(`launchctl unload "${Ft}" 2>/dev/null`)}catch{}(0,Ne.execSync)(`launchctl load "${Ft}"`),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 rt=i(require("fs")),je=i(require("path")),st=i(require("os")),V=require("child_process"),Ut="badgerclaw-watch.service",Zo=je.default.join(st.default.homedir(),".config","systemd","user"),Tr=je.default.join(Zo,Ut);function Lr(){try{return(0,V.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function Nr(){try{return(0,V.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function jr(e){let t=Nr(),o=je.default.dirname(t);return`[Unit]
107
+ </plist>`}function Qo(){if(Le.default.platform()==="darwin")try{let e=Pr();nt.default.mkdirSync(Xo,{recursive:!0}),nt.default.mkdirSync(ie.default.join(Le.default.homedir(),".badgerclaw"),{recursive:!0}),nt.default.writeFileSync(Ut,Dr(e));try{(0,Ne.execSync)(`launchctl unload "${Ut}" 2>/dev/null`)}catch{}(0,Ne.execSync)(`launchctl load "${Ut}"`),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 rt=c(require("fs")),je=c(require("path")),st=c(require("os")),V=require("child_process"),Ft="badgerclaw-watch.service",Zo=je.default.join(st.default.homedir(),".config","systemd","user"),Tr=je.default.join(Zo,Ft);function Lr(){try{return(0,V.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function Nr(){try{return(0,V.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function jr(e){let t=Nr(),o=je.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,17 +120,17 @@ StandardError=append:%h/.badgerclaw/heartbeat.log
120
120
 
121
121
  [Install]
122
122
  WantedBy=default.target
123
- `}function Br(){try{return(0,V.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function en(){if(st.default.platform()==="linux"){if(!Br()){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=Lr();rt.default.mkdirSync(Zo,{recursive:!0}),rt.default.mkdirSync(je.default.join(st.default.homedir(),".badgerclaw"),{recursive:!0}),rt.default.writeFileSync(Tr,jr(e)),(0,V.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,V.execSync)(`systemctl --user restart ${Ut}`,{stdio:"ignore"})}catch{}(0,V.execSync)(`systemctl --user enable --now ${Ut}`,{stdio:"ignore"});try{let t=(0,V.execSync)("whoami",{encoding:"utf-8"}).trim();(0,V.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 on(){let e=tn.default.platform();if(e==="darwin")return Qo();if(e==="linux")return en();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var Gt=i(require("fs")),rn=i(require("os")),sn=i(require("path")),ce=require("child_process"),W=i(require("chalk"));Ee();var nn=sn.default.join(rn.default.homedir(),".openclaw","openclaw.json");function Mr(e=!1){let t=null;try{Gt.default.existsSync(nn)&&(t=JSON.parse(Gt.default.readFileSync(nn,"utf-8"))?.gateway?.mode??null)}catch{}if(typeof t=="string"&&t.length>0)return!0;e||console.log(W.default.dim(" Setting gateway.mode=local..."));try{return ae(()=>((0,ce.execSync)("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),!0))}catch(o){return e||(console.log(W.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${o.message}`)),console.log(W.default.yellow(" Run `openclaw config set gateway.mode local` manually."))),!1}}function at(e={}){let t=e.verbose!==!1,o=a=>{t&&console.log(a)};o(W.default.dim(" Installing OpenClaw gateway service (if not present)...")),(0,ce.spawnSync)("openclaw",["gateway","install"],{stdio:t?"inherit":"pipe",shell:!0}).status!==0&&o(W.default.yellow(" \u26A0\uFE0F `openclaw gateway install` returned non-zero \u2014 continuing.")),Mr(!t),o(W.default.dim(" Starting OpenClaw gateway..."));let r=(0,ce.spawnSync)("openclaw",["gateway","start"],{stdio:t?"inherit":"pipe",shell:!0}),s="started";return r.status!==0&&(r=(0,ce.spawnSync)("openclaw",["gateway","restart"],{stdio:t?"inherit":"pipe",shell:!0}),s="restarted"),r.status!==0?{ok:!1,error:"gateway start/restart returned non-zero exit"}:{ok:!0,state:s}}function it(){if(process.platform!=="linux"||process.getuid?.()!==0)return;let e=(0,ce.spawnSync)("loginctl",["show-user","root","--property=Linger"],{encoding:"utf-8"});e.status===0&&/Linger=no/.test(e.stdout||"")&&(console.log(W.default.yellow(`
124
- \u26A0\uFE0F systemd lingering is OFF for root. The gateway will stop on SSH disconnect.`)),console.log(W.default.dim(" Enable persistence: loginctl enable-linger root")))}var Ur=2e3,Gr=12e4,dn=new an.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=bo(),t=So(e),o=`${ko}/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,ln.default)(o);let n=(0,cn.default)("Waiting for authentication...").start(),r=Po(),s=Date.now();for(;Date.now()-s<Gr;){try{let a=await r.post(`/api/v1/openclaw/cli/auth/poll/${t}`,{code_verifier:e,code_challenge:t});if(a.status===429){await new Promise(c=>setTimeout(c,5e3));continue}if(a.data?.access_token){let{access_token:c,user_id:l,expires_at:p,refresh_token:g,email:d}=a.data,C=At(),k=`openclaw-${Ht.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${C}`,Y=k;try{let{version:E}=le(),fe=await r.post("/api/v1/openclaw/register",{instance_id:k,label:Ht.default.hostname(),version:E,machine_fingerprint:C},{headers:{Authorization:`Bearer ${c}`}}),G=fe.data?.result||fe.data;G&&typeof G.instance_id=="string"&&G.instance_id.length>0&&(Y=G.instance_id)}catch(E){let fe=E?.response?.status;if(fe===403||fe===409){let G=E?.response?.data,nr=Array.isArray(G?.errors)&&typeof G.errors[0]=="string"?G.errors[0]:null,Ct=G?.detail,rr=typeof Ct=="string"?Ct:Ct?.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,sr=nr||rr||`Login refused (status ${fe}). Open the BadgerClaw app to check your subscription state.`;n.fail(Z.default.red(sr)),process.exit(1)}}Je({access_token:c,user_id:l,instance_id:Y,expires_at:p,refresh_token:g,email:d}),n.succeed(Z.default.green(`Logged in as ${ze(l)}`)),at({verbose:!0}).ok||console.log(Z.default.yellow("\n \u26A0\uFE0F Logged in, but gateway failed to start. Re-run `badgerclaw setup` to repair."));let A=await De(!0);A>0&&console.log(Z.default.green(`\u2705 ${A} bot(s) automatically paired to OpenClaw.`)),on(),it();return}}catch{}await new Promise(a=>setTimeout(a,Ur))}n.fail(Z.default.red("Authentication timed out. Please try again.")),process.exit(1)});var mn=require("commander"),Be=i(require("chalk")),ct=i(require("fs")),ye=i(require("os")),Fe=i(require("path")),Me=require("child_process");L();re();function Hr(){let e=process.platform;if(e==="darwin"){let t=Fe.default.join(ye.default.homedir(),"Library","LaunchAgents","ai.badgerclaw.watch.plist");(0,Me.spawnSync)("launchctl",["unload",t],{stdio:"ignore"});try{ct.default.unlinkSync(t)}catch{}}else if(e==="linux"){(0,Me.spawnSync)("systemctl",["--user","disable","--now","badgerclaw-watch.service"],{stdio:"ignore"});let t=Fe.default.join(ye.default.homedir(),".config","systemd","user","badgerclaw-watch.service");try{ct.default.unlinkSync(t)}catch{}(0,Me.spawnSync)("systemctl",["--user","daemon-reload"],{stdio:"ignore"})}(0,Me.spawnSync)("pkill",["-f","badgerclaw heartbeat"],{stdio:"ignore"})}function un(e){try{return ct.default.rmSync(e,{recursive:!0,force:!0}),!0}catch{return!1}}var pn=new mn.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=y();if(t)try{let a=Re(t.access_token),{version:c}=le();await a.post("/api/v1/openclaw/register",{instance_id:t.instance_id,label:ye.default.hostname(),version:c,online:!1})}catch{}if(Hr(),e.keepState){ke(),console.log(Be.default.green("Logged out \u2014 auth cleared. (state preserved with --keep-state)"));return}let o=Fe.default.join(ye.default.homedir(),".badgerclaw"),n=un(o),r=Fe.default.join(ye.default.homedir(),".openclaw","badgerclaw"),s=un(r);n||s?(console.log(Be.default.green("Logged out \u2014 local state cleared.")),console.log(Be.default.dim(` Removed: ${o}${s?`, ${r}`:""}`))):console.log(Be.default.green("Logged out."))});var gn=require("commander"),Vt=i(require("chalk"));L();var fn=new gn.Command("status").description("Show connected instance info").action(async()=>{let e=y();(!e||!Ye())&&(console.log(Vt.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(Vt.default.green("Authenticated")),console.log(` User: ${ze(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var be=require("commander"),_=i(require("chalk")),mt=i(require("ora")),ut=i(require("fs")),_n=i(require("os")),bn=i(require("path")),Sn=require("child_process");L();re();var _e=i(require("fs")),hn=i(require("os")),wn=i(require("path")),yn=require("child_process");Ee();function lt(e){let t=e.split(":")[0].replace(/^@/,"").replace(/_bot$/,""),o=wn.join(hn.homedir(),".openclaw","openclaw.json");return _e.existsSync(o)?{changed:ae(()=>{let r=JSON.parse(_e.readFileSync(o,"utf-8")),s=!1;if(r.channels?.badgerclaw?.accounts?.[t]&&(delete r.channels.badgerclaw.accounts[t],s=!0),r.agents?.list){let a=r.agents.list.length;r.agents.list=r.agents.list.filter(c=>c.id!==t),r.agents.list.length!==a&&(s=!0)}return s&&_e.writeFileSync(o,JSON.stringify(r,null,2)),s})}:{changed:!1}}function dt(){try{return(0,yn.execSync)("openclaw gateway restart",{stdio:"ignore"}),!0}catch{return!1}}function Wt(){Ye()||(console.log(_.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function Vr(e){return/^[a-z0-9_]{4,20}$/.test(e)}function $n(e){return e.replace(/_bot$/,"")}var Wr=new be.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").action(async e=>{Wt(),Vr(e)||(console.log(_.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let t=(0,mt.default)(`Creating bot "${e}"...`).start();try{await x().post("/api/v1/openclaw/bots",{username:e}),t.succeed(_.default.green(`Bot "${e}" created successfully!`))}catch(o){let n=o.response?.data?.errors?.[0]||o.message;t.fail(_.default.red(`Failed to create bot: ${n}`)),process.exit(1)}}),qr=new be.Command("list").description("List your bots").action(async()=>{Wt();let e=(0,mt.default)("Fetching bots...").start();try{let n=(await x().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),n.length===0){console.log(_.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(_.default.green(`Your bots (${n.length}):
123
+ `}function Br(){try{return(0,V.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function en(){if(st.default.platform()==="linux"){if(!Br()){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=Lr();rt.default.mkdirSync(Zo,{recursive:!0}),rt.default.mkdirSync(je.default.join(st.default.homedir(),".badgerclaw"),{recursive:!0}),rt.default.writeFileSync(Tr,jr(e)),(0,V.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,V.execSync)(`systemctl --user restart ${Ft}`,{stdio:"ignore"})}catch{}(0,V.execSync)(`systemctl --user enable --now ${Ft}`,{stdio:"ignore"});try{let t=(0,V.execSync)("whoami",{encoding:"utf-8"}).trim();(0,V.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 on(){let e=tn.default.platform();if(e==="darwin")return Qo();if(e==="linux")return en();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var Gt=c(require("fs")),rn=c(require("os")),sn=c(require("path")),ce=require("child_process"),W=c(require("chalk"));Ee();var nn=sn.default.join(rn.default.homedir(),".openclaw","openclaw.json");function Mr(e=!1){let t=null;try{Gt.default.existsSync(nn)&&(t=JSON.parse(Gt.default.readFileSync(nn,"utf-8"))?.gateway?.mode??null)}catch{}if(typeof t=="string"&&t.length>0)return!0;e||console.log(W.default.dim(" Setting gateway.mode=local..."));try{return ae(()=>((0,ce.execSync)("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),!0))}catch(o){return e||(console.log(W.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${o.message}`)),console.log(W.default.yellow(" Run `openclaw config set gateway.mode local` manually."))),!1}}function at(e={}){let t=e.verbose!==!1,o=a=>{t&&console.log(a)};o(W.default.dim(" Installing OpenClaw gateway service (if not present)...")),(0,ce.spawnSync)("openclaw",["gateway","install"],{stdio:t?"inherit":"pipe",shell:!0}).status!==0&&o(W.default.yellow(" \u26A0\uFE0F `openclaw gateway install` returned non-zero \u2014 continuing.")),Mr(!t),o(W.default.dim(" Starting OpenClaw gateway..."));let r=(0,ce.spawnSync)("openclaw",["gateway","start"],{stdio:t?"inherit":"pipe",shell:!0}),s="started";return r.status!==0&&(r=(0,ce.spawnSync)("openclaw",["gateway","restart"],{stdio:t?"inherit":"pipe",shell:!0}),s="restarted"),r.status!==0?{ok:!1,error:"gateway start/restart returned non-zero exit"}:{ok:!0,state:s}}function it(){if(process.platform!=="linux"||process.getuid?.()!==0)return;let e=(0,ce.spawnSync)("loginctl",["show-user","root","--property=Linger"],{encoding:"utf-8"});e.status===0&&/Linger=no/.test(e.stdout||"")&&(console.log(W.default.yellow(`
124
+ \u26A0\uFE0F systemd lingering is OFF for root. The gateway will stop on SSH disconnect.`)),console.log(W.default.dim(" Enable persistence: loginctl enable-linger root")))}var Fr=2e3,Gr=12e4,dn=new an.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=bo(),t=So(e),o=`${ko}/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,ln.default)(o);let n=(0,cn.default)("Waiting for authentication...").start(),r=Po(),s=Date.now();for(;Date.now()-s<Gr;){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:i,expires_at:p,refresh_token:g,email:d}=a.data,C=At(),k=`openclaw-${Ht.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${C}`,Y=k;try{let{version:E}=le(),fe=await r.post("/api/v1/openclaw/register",{instance_id:k,label:Ht.default.hostname(),version:E,machine_fingerprint:C},{headers:{Authorization:`Bearer ${l}`}}),G=fe.data?.result||fe.data;G&&typeof G.instance_id=="string"&&G.instance_id.length>0&&(Y=G.instance_id)}catch(E){let fe=E?.response?.status;if(fe===403||fe===409){let G=E?.response?.data,nr=Array.isArray(G?.errors)&&typeof G.errors[0]=="string"?G.errors[0]:null,Ct=G?.detail,rr=typeof Ct=="string"?Ct:Ct?.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,sr=nr||rr||`Login refused (status ${fe}). Open the BadgerClaw app to check your subscription state.`;n.fail(Z.default.red(sr)),process.exit(1)}}Je({access_token:l,user_id:i,instance_id:Y,expires_at:p,refresh_token:g,email:d}),n.succeed(Z.default.green(`Logged in as ${ze(i)}`)),at({verbose:!0}).ok||console.log(Z.default.yellow("\n \u26A0\uFE0F Logged in, but gateway failed to start. Re-run `badgerclaw setup` to repair."));let A=await De(!0);A>0&&console.log(Z.default.green(`\u2705 ${A} bot(s) automatically paired to OpenClaw.`)),on(),it();return}}catch{}await new Promise(a=>setTimeout(a,Fr))}n.fail(Z.default.red("Authentication timed out. Please try again.")),process.exit(1)});var mn=require("commander"),Be=c(require("chalk")),ct=c(require("fs")),ye=c(require("os")),Ue=c(require("path")),Me=require("child_process");L();re();function Hr(){let e=process.platform;if(e==="darwin"){let t=Ue.default.join(ye.default.homedir(),"Library","LaunchAgents","ai.badgerclaw.watch.plist");(0,Me.spawnSync)("launchctl",["unload",t],{stdio:"ignore"});try{ct.default.unlinkSync(t)}catch{}}else if(e==="linux"){(0,Me.spawnSync)("systemctl",["--user","disable","--now","badgerclaw-watch.service"],{stdio:"ignore"});let t=Ue.default.join(ye.default.homedir(),".config","systemd","user","badgerclaw-watch.service");try{ct.default.unlinkSync(t)}catch{}(0,Me.spawnSync)("systemctl",["--user","daemon-reload"],{stdio:"ignore"})}(0,Me.spawnSync)("pkill",["-f","badgerclaw heartbeat"],{stdio:"ignore"})}function un(e){try{return ct.default.rmSync(e,{recursive:!0,force:!0}),!0}catch{return!1}}var pn=new mn.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=y();if(t)try{let a=Re(t.access_token),{version:l}=le();await a.post("/api/v1/openclaw/register",{instance_id:t.instance_id,label:ye.default.hostname(),version:l,online:!1})}catch{}if(Hr(),e.keepState){ke(),console.log(Be.default.green("Logged out \u2014 auth cleared. (state preserved with --keep-state)"));return}let o=Ue.default.join(ye.default.homedir(),".badgerclaw"),n=un(o),r=Ue.default.join(ye.default.homedir(),".openclaw","badgerclaw"),s=un(r);n||s?(console.log(Be.default.green("Logged out \u2014 local state cleared.")),console.log(Be.default.dim(` Removed: ${o}${s?`, ${r}`:""}`))):console.log(Be.default.green("Logged out."))});var gn=require("commander"),Vt=c(require("chalk"));L();var fn=new gn.Command("status").description("Show connected instance info").action(async()=>{let e=y();(!e||!Ye())&&(console.log(Vt.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(Vt.default.green("Authenticated")),console.log(` User: ${ze(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var be=require("commander"),_=c(require("chalk")),mt=c(require("ora")),ut=c(require("fs")),_n=c(require("os")),bn=c(require("path")),Sn=require("child_process");L();re();var _e=c(require("fs")),hn=c(require("os")),wn=c(require("path")),yn=require("child_process");Ee();function lt(e){let t=e.split(":")[0].replace(/^@/,"").replace(/_bot$/,""),o=wn.join(hn.homedir(),".openclaw","openclaw.json");return _e.existsSync(o)?{changed:ae(()=>{let r=JSON.parse(_e.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&&_e.writeFileSync(o,JSON.stringify(r,null,2)),s})}:{changed:!1}}function dt(){try{return(0,yn.execSync)("openclaw gateway restart",{stdio:"ignore"}),!0}catch{return!1}}function Wt(){Ye()||(console.log(_.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function Vr(e){return/^[a-z0-9_]{4,20}$/.test(e)}function $n(e){return e.replace(/_bot$/,"")}var Wr=new be.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").action(async e=>{Wt(),Vr(e)||(console.log(_.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let t=(0,mt.default)(`Creating bot "${e}"...`).start();try{await x().post("/api/v1/openclaw/bots",{username:e}),t.succeed(_.default.green(`Bot "${e}" created successfully!`))}catch(o){let n=o.response?.data?.errors?.[0]||o.message;t.fail(_.default.red(`Failed to create bot: ${n}`)),process.exit(1)}}),qr=new be.Command("list").description("List your bots").action(async()=>{Wt();let e=(0,mt.default)("Fetching bots...").start();try{let n=(await x().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),n.length===0){console.log(_.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(_.default.green(`Your bots (${n.length}):
125
125
  `));for(let r of n){let s=$n(r.username||r.name),a=r.active===!1?_.default.dim("deactivated"):r.openclaw_connected?_.default.green("connected"):_.default.gray("disconnected");console.log(` ${_.default.bold(s)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(_.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),Kr=new be.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{Wt();let t=(0,mt.default)(`Deactivating bot "${e}"...`).start();try{await x().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(_.default.green(`Bot "${e}" deactivated.`));let{changed:n}=lt(e);n&&(console.log(_.default.dim(" Removed from openclaw.json")),dt()&&console.log(_.default.dim(" Gateway restarted")))}catch(o){let n=o.response?.data?.errors?.[0]||o.message;t.fail(_.default.red(`Failed to deactivate bot: ${n}`)),process.exit(1)}});function Jr(e){let t=e.trim();return t.startsWith("@")&&(t=t.slice(1)),t.includes(":")&&(t=t.split(":")[0]),$n(t)}function Yr(e){let t=e.replace(/[^a-zA-Z0-9_.-]/g,"_")||"default";return bn.default.join(_n.default.homedir(),".openclaw","badgerclaw","quarantine",`${t}.json`)}var zr=new be.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=Jr(e);t||(console.log(_.default.red(`Couldn't parse bot name "${e}".`)),process.exit(1));let o=Yr(t),n=!1;if(ut.default.existsSync(o))try{let r=JSON.parse(ut.default.readFileSync(o,"utf-8")),s=r.failureCount??"?",a=r.quarantinedAt??"?";console.log(_.default.dim(` Quarantine for "${t}" \u2014 ${s} failures, since ${a}`)),ut.default.unlinkSync(o),n=!0}catch(r){console.log(_.default.red(`Failed to clear quarantine ledger at ${o}: ${r.message}`)),process.exit(1)}console.log(n?_.default.green(`\u2705 Cleared quarantine for "${t}"`):_.default.dim(` No quarantine file for "${t}" \u2014 already healthy or never quarantined.`)),console.log(_.default.dim(" Restarting OpenClaw gateway so the refresh chain runs..."));try{(0,Sn.execSync)("openclaw gateway restart",{stdio:"inherit"})}catch(r){console.log(_.default.yellow(` Gateway restart command failed: ${r.message}`)),console.log(_.default.yellow(" Run `openclaw gateway restart` manually.")),process.exit(1)}console.log(_.default.green(`
126
- \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(_.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(_.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(_.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(_.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),Cn=new be.Command("bot").description("Manage bots").addCommand(Wr).addCommand(qr).addCommand(Kr).addCommand(zr);Te();var qn=require("commander"),h=i(require("chalk"));L();z();Te();de();Ve();po();re();he();var Kn=new qn.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{let e=y();e||(console.log(h.default.yellow("Not logged in.")),process.exit(1)),await De(!1),console.log(h.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=new t(`${N}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${e.access_token}`}});o.onmessage=async n=>{try{let r=JSON.parse(n.data);if(r.type==="pair"){let s=r.target_instance_id;if(s&&s!==U()){console.log(h.default.dim(`
126
+ \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(_.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(_.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(_.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(_.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),Cn=new be.Command("bot").description("Manage bots").addCommand(Wr).addCommand(qr).addCommand(Kr).addCommand(zr);Te();var qn=require("commander"),h=c(require("chalk"));L();z();Te();de();Ve();po();re();he();var Kn=new qn.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{let e=y();e||(console.log(h.default.yellow("Not logged in.")),process.exit(1)),await De(!1),console.log(h.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=new t(`${N}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${e.access_token}`}});o.onmessage=async n=>{try{let r=JSON.parse(n.data);if(r.type==="pair"){let s=r.target_instance_id;if(s&&s!==F()){console.log(h.default.dim(`
127
127
  \u{1F4F1} Pair event for ${r.bot_name} targets ${s} \u2014 not us, skipping`));return}console.log(h.default.cyan(`
128
128
  \u{1F4F1} Pair event received: ${r.bot_name}`)),await Oe(r.pair_code,r.bot_name,r.bot_user_id,!1);try{let{execSync:a}=await import("child_process");a("openclaw gateway restart",{stdio:"ignore"}),console.log(h.default.green(" \u2705 Gateway restarted \u2014 bot is live!"))}catch{console.log(h.default.dim(" Gateway restart failed \u2014 run: openclaw gateway restart"))}}else if(r.type==="gateway-restart"){console.log(h.default.cyan(`
129
- \u{1F504} Remote gateway-restart command received`));let s=await Se();s.success?console.log(h.default.green(` \u2705 Gateway restarted: ${s.message}`)):console.log(h.default.red(` \u274C Gateway restart failed: ${s.message}`));try{await R(),console.log(h.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(h.default.dim(" Could not push heartbeat."))}}else if((r.type==="bot.delete"||r.type==="bot.disconnect")&&r.bot_user_id){let s=r.bot_user_id,a=r.type==="bot.delete"?"deleted":"disconnected",c=r.type==="bot.delete"?"\u{1F5D1}\uFE0F ":"\u{1F50C}";console.log(h.default.yellow(`
130
- ${c} Bot ${a}: ${s} \u2014 removing from OpenClaw config...`));try{let{changed:l}=lt(s);l?(console.log(h.default.green(" \u2705 Removed from openclaw.json")),dt()?console.log(h.default.green(" \u2705 Gateway restarted")):console.log(h.default.dim(" Gateway restart failed \u2014 restart manually"))):console.log(h.default.dim(" Account not found in openclaw.json \u2014 nothing to remove"))}catch(l){console.log(h.default.red(` Failed to update openclaw.json: ${l}`))}}else if(r.type==="claude_code.start"&&r.bot_id&&r.room_id){console.log(h.default.cyan(`
129
+ \u{1F504} Remote gateway-restart command received`));let s=await Se();s.success?console.log(h.default.green(` \u2705 Gateway restarted: ${s.message}`)):console.log(h.default.red(` \u274C Gateway restart failed: ${s.message}`));try{await R(),console.log(h.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(h.default.dim(" Could not push heartbeat."))}}else if((r.type==="bot.delete"||r.type==="bot.disconnect")&&r.bot_user_id){let s=r.bot_user_id,a=r.type==="bot.delete"?"deleted":"disconnected",l=r.type==="bot.delete"?"\u{1F5D1}\uFE0F ":"\u{1F50C}";console.log(h.default.yellow(`
130
+ ${l} Bot ${a}: ${s} \u2014 removing from OpenClaw config...`));try{let{changed:i}=lt(s);i?(console.log(h.default.green(" \u2705 Removed from openclaw.json")),dt()?console.log(h.default.green(" \u2705 Gateway restarted")):console.log(h.default.dim(" Gateway restart failed \u2014 restart manually"))):console.log(h.default.dim(" Account not found in openclaw.json \u2014 nothing to remove"))}catch(i){console.log(h.default.red(` Failed to update openclaw.json: ${i}`))}}else if(r.type==="claude_code.start"&&r.bot_id&&r.room_id){console.log(h.default.cyan(`
131
131
  \u{1F916} Claude Code START received: bot=${r.bot_id} room=${r.room_id}`));try{let s=await K({id:r.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:r.bot_id,room_id:r.room_id,session_id:r.session_id}});if(console.log(s.success?h.default.green(` \u2705 ${s.message}`):h.default.red(` \u274C ${s.message}`)),r.command_id)try{await x().post(`/api/v1/dashboard/commands/${r.command_id}/result`,{status:s.success?"success":"failed",result:s.message})}catch{}try{await R()}catch{}}catch(s){console.log(h.default.red(` Claude Code start error: ${s.message}`))}}else if(r.type==="claude_code.stop"&&r.bot_id&&r.room_id){console.log(h.default.cyan(`
132
132
  \u{1F916} Claude Code STOP received: bot=${r.bot_id} room=${r.room_id}`));try{let s=await K({id:r.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:r.bot_id,room_id:r.room_id,session_id:r.session_id}});if(console.log(s.success?h.default.green(` \u2705 ${s.message}`):h.default.red(` \u274C ${s.message}`)),r.command_id)try{await x().post(`/api/v1/dashboard/commands/${r.command_id}/result`,{status:s.success?"success":"failed",result:s.message})}catch{}try{await R()}catch{}}catch(s){console.log(h.default.red(` Claude Code stop error: ${s.message}`))}}else if(r.type==="command.execute"&&r.command_id){console.log(h.default.cyan(`
133
- \u26A1 SSE command received: ${r.command_type} (${r.command_id})`));try{let s=x();await s.post(`/api/v1/dashboard/commands/${r.command_id}/ack`);let a=await K({id:r.command_id,command_type:r.command_type,payload:r.payload});console.log(a.success?h.default.green(` \u2705 ${a.message}`):h.default.red(` \u274C ${a.message}`)),await s.post(`/api/v1/dashboard/commands/${r.command_id}/result`,{status:a.success?"success":"failed",result:a.message,new_version:a.newVersion||null});try{await R()}catch{}r.command_type==="update_cli"&&a.success&&(console.log(h.default.cyan(" CLI updated \u2014 restarting in 2s...")),setTimeout(()=>process.exit(0),2e3))}catch(s){console.log(h.default.red(` Command ${r.command_id} error: ${s.message}`))}}}catch{}},o.onerror=()=>{console.log(h.default.dim(" Reconnecting..."))},await new Promise(()=>{})});var Jn=require("commander"),u=i(require("chalk")),J=require("child_process"),$=i(require("fs")),qe=i(require("os")),te=i(require("path"));z();gt();var M=te.default.join(qe.default.homedir(),".openclaw","openclaw.json"),We=M+".badgerclaw-stash",St=te.default.join(qe.default.homedir(),".openclaw","npm"),fo=te.default.join(St,"package.json");async function Ws(){try{let e=await fetch(`${N}/api/v1/dashboard/versions/latest`,{headers:{Accept:"application/json"}});if(!e.ok)return{cli:null,plugin:null,openclaw:null};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)}}catch{return{cli:null,plugin:null,openclaw:null}}}function qs(){if(!$.default.existsSync(M))return null;try{let e=JSON.parse($.default.readFileSync(M,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,$.default.writeFileSync(M,JSON.stringify(e,null,2)),$.default.writeFileSync(We,JSON.stringify(t,null,2)),t):null}catch{return null}}function Ks(){if(!$.default.existsSync(M))return null;try{let e=JSON.parse($.default.readFileSync(M,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function Js(e){if(e&&$.default.existsSync(M))try{let t=JSON.parse($.default.readFileSync(M,"utf-8"));t.gateway={...e,...t.gateway||{}},$.default.writeFileSync(M,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 Ys(){if($.default.existsSync(We))try{let e=JSON.parse($.default.readFileSync(We,"utf-8")),t=JSON.parse($.default.readFileSync(M,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,$.default.writeFileSync(M,JSON.stringify(t,null,2)),$.default.unlinkSync(We)}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: ${We}`))}}async function zs(e){return new Promise(t=>{let o=(0,J.spawn)("openclaw",["plugins","install",e,"--force","--dangerously-force-unsafe-install"],{stdio:["ignore","pipe","pipe"],shell:!0}),n="",r=!1,s=!1,a=/Installed plugin:|Restart the gateway to load plugins/,c=()=>{r||s||(r=!0,setTimeout(()=>{if(!s){try{o.kill("SIGTERM")}catch{}setTimeout(()=>{if(!s)try{o.kill("SIGKILL")}catch{}},1e3)}},3e3))},l=(p,g)=>{g.write(p),n+=p.toString("utf-8"),a.test(n)&&c()};o.stdout.on("data",p=>l(p,process.stdout)),o.stderr.on("data",p=>l(p,process.stderr)),o.on("exit",p=>{s=!0,t({status:r?0:p??1})}),o.on("error",p=>{s||(s=!0,console.error(u.default.red(` openclaw spawn error: ${p.message}`)),t({status:1}))})})}function Xs(){if(!$.default.existsSync(fo))return!1;let e;try{e=JSON.parse($.default.readFileSync(fo,"utf-8"))}catch{return!1}let t=!1;return e.overrides&&typeof e.overrides=="object"&&"uuid"in e.overrides&&(delete e.overrides.uuid,t=!0),e.openclaw&&Array.isArray(e.openclaw.managedOverrides)&&e.openclaw.managedOverrides.includes("uuid")&&(e.openclaw.managedOverrides=e.openclaw.managedOverrides.filter(o=>o!=="uuid"),t=!0),t?($.default.writeFileSync(fo,JSON.stringify(e,null,2)+`
133
+ \u26A1 SSE command received: ${r.command_type} (${r.command_id})`));try{let s=x();await s.post(`/api/v1/dashboard/commands/${r.command_id}/ack`);let a=await K({id:r.command_id,command_type:r.command_type,payload:r.payload});console.log(a.success?h.default.green(` \u2705 ${a.message}`):h.default.red(` \u274C ${a.message}`)),await s.post(`/api/v1/dashboard/commands/${r.command_id}/result`,{status:a.success?"success":"failed",result:a.message,new_version:a.newVersion||null});try{await R()}catch{}r.command_type==="update_cli"&&a.success&&(console.log(h.default.cyan(" CLI updated \u2014 restarting in 2s...")),setTimeout(()=>process.exit(0),2e3))}catch(s){console.log(h.default.red(` Command ${r.command_id} error: ${s.message}`))}}}catch{}},o.onerror=()=>{console.log(h.default.dim(" Reconnecting..."))},await new Promise(()=>{})});var Jn=require("commander"),u=c(require("chalk")),J=require("child_process"),$=c(require("fs")),qe=c(require("os")),te=c(require("path"));z();gt();var M=te.default.join(qe.default.homedir(),".openclaw","openclaw.json"),We=M+".badgerclaw-stash",St=te.default.join(qe.default.homedir(),".openclaw","npm"),fo=te.default.join(St,"package.json");async function Ws(){try{let e=await fetch(`${N}/api/v1/dashboard/versions/latest`,{headers:{Accept:"application/json"}});if(!e.ok)return{cli:null,plugin:null,openclaw:null};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)}}catch{return{cli:null,plugin:null,openclaw:null}}}function qs(){if(!$.default.existsSync(M))return null;try{let e=JSON.parse($.default.readFileSync(M,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,$.default.writeFileSync(M,JSON.stringify(e,null,2)),$.default.writeFileSync(We,JSON.stringify(t,null,2)),t):null}catch{return null}}function Ks(){if(!$.default.existsSync(M))return null;try{let e=JSON.parse($.default.readFileSync(M,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function Js(e){if(e&&$.default.existsSync(M))try{let t=JSON.parse($.default.readFileSync(M,"utf-8"));t.gateway={...e,...t.gateway||{}},$.default.writeFileSync(M,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 Ys(){if($.default.existsSync(We))try{let e=JSON.parse($.default.readFileSync(We,"utf-8")),t=JSON.parse($.default.readFileSync(M,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,$.default.writeFileSync(M,JSON.stringify(t,null,2)),$.default.unlinkSync(We)}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: ${We}`))}}async function zs(e){return new Promise(t=>{let o=(0,J.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))},i=(p,g)=>{g.write(p),n+=p.toString("utf-8"),a.test(n)&&l()};o.stdout.on("data",p=>i(p,process.stdout)),o.stderr.on("data",p=>i(p,process.stderr)),o.on("exit",p=>{s=!0,t({status:r?0:p??1})}),o.on("error",p=>{s||(s=!0,console.error(u.default.red(` openclaw spawn error: ${p.message}`)),t({status:1}))})})}function Xs(){if(!$.default.existsSync(fo))return!1;let e;try{e=JSON.parse($.default.readFileSync(fo,"utf-8"))}catch{return!1}let t=!1;return e.overrides&&typeof e.overrides=="object"&&"uuid"in e.overrides&&(delete e.overrides.uuid,t=!0),e.openclaw&&Array.isArray(e.openclaw.managedOverrides)&&e.openclaw.managedOverrides.includes("uuid")&&(e.openclaw.managedOverrides=e.openclaw.managedOverrides.filter(o=>o!=="uuid"),t=!0),t?($.default.writeFileSync(fo,JSON.stringify(e,null,2)+`
134
134
  `),!0):!1}async function Qs(){let{detectCapabilities:e}=await Promise.resolve().then(()=>(Zt(),Tn)),{pushHeartbeat:t}=await Promise.resolve().then(()=>(Ve(),Wn));console.log(u.default.green(`
135
135
  \u{1F9A1} BadgerClaw \u2014 capability refresh
136
136
  `));let o=e();console.log(u.default.dim(" Detected on this host:")),console.log(u.default.dim(` OpenClaw : ${ho(o.openclaw)}`)),console.log(u.default.dim(` Hermes : ${ho(o.hermes)}`)),console.log(u.default.dim(` Docker : ${ho(o.docker)}`)),o.disk_free_gb!==null&&console.log(u.default.dim(` Disk free: ${o.disk_free_gb} GB`));try{await t(),console.log(u.default.green(`
@@ -139,12 +139,12 @@ ${c} Bot ${a}: ${s} \u2014 removing from OpenClaw config...`));try{let{changed:l
139
139
  \u274C Failed to push capabilities: ${r}`)),process.exit(1)}}function ho(e){return e.installed?e.version?`installed (${e.version})`:e.image?`installed (${e.image})`:"installed":"not installed"}var Yn=new Jn.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.").action(async e=>{if(e.refresh){await Qs();return}console.log(u.default.green(`
140
140
  \u{1F9A1} BadgerClaw Setup
141
141
  `));let t=await Ws();if(t.cli){let d=zt();d!==t.cli?(console.log(u.default.dim(` Updating CLI: ${d} \u2192 ${t.cli} (supported)...`)),(0,J.spawnSync)("npm",["install","-g",`badgerclaw@${t.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 ${t.cli}`))):console.log(u.default.dim(` CLI already at approved version ${d}.`))}if(t.openclaw){let d=Ce();d!==t.openclaw?(console.log(d===null?u.default.dim(` Installing OpenClaw ${t.openclaw} (supported)...`):u.default.dim(` Updating OpenClaw: ${d} \u2192 ${t.openclaw} (supported)...`)),(0,J.spawnSync)("npm",["install","-g",`openclaw@${t.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 ${t.openclaw}`))):console.log(u.default.dim(` OpenClaw already at approved version ${d}.`))}else Ce()===null&&(console.log(u.default.yellow(" \u26A0\uFE0F No approved OpenClaw version and none installed \u2014 installing latest from npm.")),(0,J.spawnSync)("npm",["install","-g","openclaw"],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red(`
142
- \u274C OpenClaw install failed.`)),process.exit(1)));let o=qs();o&&console.log(u.default.dim(" Existing bot config stashed temporarily..."));let n=Ks();(0,J.spawnSync)("openclaw",["gateway","stop"],{stdio:"pipe",shell:!0,timeout:1e4});let r=[te.default.join(qe.default.homedir(),".openclaw","extensions","badgerclaw"),te.default.join(qe.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect")],s=[],a=[],c=d=>{let C=`${d}.bc-setup-stash-${Date.now()}-${Math.floor(Math.random()*1e6)}`,k=(0,J.spawnSync)("mv",["-f",d,C],{encoding:"utf-8"});return k.status===0?{ok:!0,stash:C}:{ok:!1,error:(k.stderr||"").trim()||`exit ${k.status}`}};for(let d of r)if($.default.existsSync(d))try{$.default.rmSync(d,{recursive:!0,force:!0}),s.push(d)}catch(C){let k=c(d);k.ok?(a.push(`${d} \u2192 ${k.stash}`),console.log(u.default.yellow(` \u26A0\uFE0F Could not delete ${d} (${C.message}); renamed it aside instead.`))):(console.log(u.default.red(` \u274C Could not delete ${d} (${C.message})`)),console.log(u.default.red(` Could not rename ${d} aside either (${k.error}). Plugin install will likely fail.`)))}s.length>0&&console.log(u.default.dim(` Cleared existing plugin director${s.length>1?"ies":"y"}.`)),a.length>0&&console.log(u.default.dim(` Renamed busy install${a.length>1?"s":""} aside: ${a.join(", ")}`));let l=t.plugin?`@badgerclaw/connect@${t.plugin}`:"@badgerclaw/connect";t.plugin?console.log(u.default.dim(` Installing ${l} (supported)...`)):console.log(u.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let p=await zs(l);if(o&&(Ys(),console.log(u.default.dim(" Bot config restored."))),n&&(Js(n),console.log(u.default.dim(" Gateway config restored."))),p.status!==0&&(console.log(u.default.red(`
142
+ \u274C OpenClaw install failed.`)),process.exit(1)));let o=qs();o&&console.log(u.default.dim(" Existing bot config stashed temporarily..."));let n=Ks();(0,J.spawnSync)("openclaw",["gateway","stop"],{stdio:"pipe",shell:!0,timeout:1e4});let r=[te.default.join(qe.default.homedir(),".openclaw","extensions","badgerclaw"),te.default.join(qe.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect")],s=[],a=[],l=d=>{let C=`${d}.bc-setup-stash-${Date.now()}-${Math.floor(Math.random()*1e6)}`,k=(0,J.spawnSync)("mv",["-f",d,C],{encoding:"utf-8"});return k.status===0?{ok:!0,stash:C}:{ok:!1,error:(k.stderr||"").trim()||`exit ${k.status}`}};for(let d of r)if($.default.existsSync(d))try{$.default.rmSync(d,{recursive:!0,force:!0}),s.push(d)}catch(C){let k=l(d);k.ok?(a.push(`${d} \u2192 ${k.stash}`),console.log(u.default.yellow(` \u26A0\uFE0F Could not delete ${d} (${C.message}); renamed it aside instead.`))):(console.log(u.default.red(` \u274C Could not delete ${d} (${C.message})`)),console.log(u.default.red(` Could not rename ${d} aside either (${k.error}). Plugin install will likely fail.`)))}s.length>0&&console.log(u.default.dim(` Cleared existing plugin director${s.length>1?"ies":"y"}.`)),a.length>0&&console.log(u.default.dim(` Renamed busy install${a.length>1?"s":""} aside: ${a.join(", ")}`));let i=t.plugin?`@badgerclaw/connect@${t.plugin}`:"@badgerclaw/connect";t.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 p=await zs(i);if(o&&(Ys(),console.log(u.default.dim(" Bot config restored."))),n&&(Js(n),console.log(u.default.dim(" Gateway config restored."))),p.status!==0&&(console.log(u.default.red(`
143
143
  \u274C Plugin install failed. Your bot config has been restored.`)),process.exit(1)),console.log(u.default.green(`
144
144
  \u2705 BadgerClaw plugin installed successfully!`)),Xs()){console.log(u.default.dim(" Stripping OpenClaw uuid:14 override (breaks request@2.88 in matrix-bot-sdk)..."));try{$.default.rmSync(te.default.join(St,"node_modules","uuid"),{recursive:!0,force:!0})}catch{}try{$.default.rmSync(te.default.join(St,"package-lock.json"),{force:!0})}catch{}(0,J.spawnSync)("npm",["install"],{cwd:St,stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red(`
145
145
  \u274C npm install failed after removing uuid override. Bot will not reply correctly until this is resolved.`)),process.exit(1)),console.log(u.default.green(" \u2705 uuid override stripped + npm tree re-resolved."))}console.log(""),at({verbose:!0}).ok||(console.log(u.default.red(`
146
- \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)),console.log(u.default.green(" \u2705 Gateway is running.")),console.log(u.default.dim("\nNext: run `badgerclaw login` to authenticate.")),it()});Ve();var Xn=require("commander"),v=i(require("chalk"));L();he();de();var Qn=new Xn.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{y()||(console.log(v.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=le(),o=Xe(),n=await Ue();console.log(v.default.bold.green(`
146
+ \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)),console.log(u.default.green(" \u2705 Gateway is running.")),console.log(u.default.dim("\nNext: run `badgerclaw login` to authenticate.")),it()});Ve();var Xn=require("commander"),v=c(require("chalk"));L();he();de();var Qn=new Xn.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{y()||(console.log(v.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=le(),o=Xe(),n=await Fe();console.log(v.default.bold.green(`
147
147
  BadgerClaw Dashboard
148
- `)),console.log(v.default.bold(" Instance")),console.log(` ID: ${U()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${n.pluginVersion}`),console.log(),console.log(v.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${zn(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let r=n.status==="running"?v.default.green:n.status==="error"?v.default.red:v.default.yellow;if(console.log(v.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(v.default.bold(" Bots")),console.log(v.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log(v.default.bold(` Bots (${n.bots.length})`)),console.log();for(let s of n.bots){let a=s.status==="running"?v.default.green:s.status==="error"?v.default.red:v.default.yellow;if(console.log(` ${v.default.bold(s.botUsername)} ${a(`[${s.status}]`)}`),console.log(` ID: ${s.botId}`),console.log(` Uptime: ${zn(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: ${v.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(v.default.dim(" Rooms:"));for(let c of s.roomDetails)console.log(v.default.dim(` ${c.roomName} \u2014 ${c.messagesInRoom} msgs, last: ${c.lastActivityInRoom??"N/A"}`))}console.log()}}console.log(v.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function zn(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 wo=require("commander"),ve=i(require("chalk")),Zn=i(require("ora"));L();de();Ve();var Zs=new wo.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{y()||(console.log(ve.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,Zn.default)("Restarting gateway...").start(),o=await Se();if(o.success){t.succeed(ve.default.green(`Gateway restarted: ${o.message}`));try{await R(),console.log(ve.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(ve.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(ve.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),er=new wo.Command("gateway").description("Manage the OpenClaw gateway").addCommand(Zs);var ne=require("commander"),w=i(require("chalk")),ge=i(require("ora")),oe=i(require("axios"));wt();L();var pe="http://localhost:7331",ea=new ne.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=>{y()||(console.log(w.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,ge.default)("Starting Claude Code session...").start();try{await oe.default.post(`${pe}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),s.text="Gateway toggled \u2014 launching MCP server...";let c=so({sessionId:o,port:n,projectDir:r}).pid||0;await new Promise(l=>setTimeout(l,1500)),s.text="MCP server running \u2014 launching Claude Code...",ao({sessionId:o,port:n,projectDir:r}),io(o,0,c,n,r),s.succeed(w.default.green("Claude Code session started")+w.default.dim(` (session: ${o}, port: ${n})`)),console.log(w.default.dim(` Bot: ${e.bot}`)),console.log(w.default.dim(` Room: ${e.room}`)),console.log(w.default.dim(` Project: ${r}`)),console.log(w.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let c=a.response?.data?.message||a.message||"Unknown error";s.fail(w.default.red(`Failed to start Claude Code: ${c}`)),process.exit(1)}}),ta=new ne.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=>{y()||(console.log(w.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,ge.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await oe.default.post(`${pe}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let n=e.sessionId;if(!n)try{let a=((await oe.default.get(`${pe}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(c=>c.botId===e.bot&&c.roomId===e.room);a&&(n=a.sessionId)}catch{}n?(co(n),o.succeed(w.default.green(`Claude Code session stopped (${n})`))):(o.succeed(w.default.green("Claude Code toggled off at gateway")),console.log(w.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(w.default.red(`Failed to stop Claude Code: ${r}`)),process.exit(1)}}),oa=new ne.Command("status").description("Show active Claude Code sessions").action(async()=>{y()||(console.log(w.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,ge.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await oe.default.get(`${pe}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let n=lo();if(t.stop(),o.length===0&&n.length===0){console.log(w.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(w.default.bold(`
148
+ `)),console.log(v.default.bold(" Instance")),console.log(` ID: ${F()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${n.pluginVersion}`),console.log(),console.log(v.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${zn(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let r=n.status==="running"?v.default.green:n.status==="error"?v.default.red:v.default.yellow;if(console.log(v.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(v.default.bold(" Bots")),console.log(v.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log(v.default.bold(` Bots (${n.bots.length})`)),console.log();for(let s of n.bots){let a=s.status==="running"?v.default.green:s.status==="error"?v.default.red:v.default.yellow;if(console.log(` ${v.default.bold(s.botUsername)} ${a(`[${s.status}]`)}`),console.log(` ID: ${s.botId}`),console.log(` Uptime: ${zn(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: ${v.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(v.default.dim(" Rooms:"));for(let l of s.roomDetails)console.log(v.default.dim(` ${l.roomName} \u2014 ${l.messagesInRoom} msgs, last: ${l.lastActivityInRoom??"N/A"}`))}console.log()}}console.log(v.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function zn(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 wo=require("commander"),ve=c(require("chalk")),Zn=c(require("ora"));L();de();Ve();var Zs=new wo.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{y()||(console.log(ve.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,Zn.default)("Restarting gateway...").start(),o=await Se();if(o.success){t.succeed(ve.default.green(`Gateway restarted: ${o.message}`));try{await R(),console.log(ve.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(ve.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(ve.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),er=new wo.Command("gateway").description("Manage the OpenClaw gateway").addCommand(Zs);var ne=require("commander"),w=c(require("chalk")),ge=c(require("ora")),oe=c(require("axios"));wt();L();var pe="http://localhost:7331",ea=new ne.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=>{y()||(console.log(w.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,ge.default)("Starting Claude Code session...").start();try{await oe.default.post(`${pe}/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=so({sessionId:o,port:n,projectDir:r}).pid||0;await new Promise(i=>setTimeout(i,1500)),s.text="MCP server running \u2014 launching Claude Code...",ao({sessionId:o,port:n,projectDir:r}),io(o,0,l,n,r),s.succeed(w.default.green("Claude Code session started")+w.default.dim(` (session: ${o}, port: ${n})`)),console.log(w.default.dim(` Bot: ${e.bot}`)),console.log(w.default.dim(` Room: ${e.room}`)),console.log(w.default.dim(` Project: ${r}`)),console.log(w.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(w.default.red(`Failed to start Claude Code: ${l}`)),process.exit(1)}}),ta=new ne.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=>{y()||(console.log(w.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,ge.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await oe.default.post(`${pe}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let n=e.sessionId;if(!n)try{let a=((await oe.default.get(`${pe}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(l=>l.botId===e.bot&&l.roomId===e.room);a&&(n=a.sessionId)}catch{}n?(co(n),o.succeed(w.default.green(`Claude Code session stopped (${n})`))):(o.succeed(w.default.green("Claude Code toggled off at gateway")),console.log(w.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(w.default.red(`Failed to stop Claude Code: ${r}`)),process.exit(1)}}),oa=new ne.Command("status").description("Show active Claude Code sessions").action(async()=>{y()||(console.log(w.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,ge.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await oe.default.get(`${pe}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let n=lo();if(t.stop(),o.length===0&&n.length===0){console.log(w.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(w.default.bold(`
149
149
  Gateway Claude Code Rooms:`)),console.log(w.default.dim(" Bot".padEnd(30)+"Room".padEnd(30)+"Session".padEnd(20)+"Enabled")),console.log(w.default.dim(" "+"-".repeat(88)));for(let r of o){let s=r.enabled?w.default.green("ON"):w.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(w.default.bold(`
150
- Local Sessions:`)),console.log(w.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(w.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(w.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),na=new ne.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,ge.default)("Grouping bot+room into session...").start();try{await oe.default.post(`${pe}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:e.session},{timeout:1e4}),t.succeed(w.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(w.default.red(`Failed to group: ${n}`)),process.exit(1)}}),ra=new ne.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,ge.default)("Adding user to allowlist...").start();try{await oe.default.post(`${pe}/claude-code/allow`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(w.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(w.default.red(`Failed to add user: ${n}`)),process.exit(1)}}),sa=new ne.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,ge.default)("Removing user from allowlist...").start();try{await oe.default.post(`${pe}/claude-code/revoke`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(w.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(w.default.red(`Failed to revoke user: ${n}`)),process.exit(1)}}),tr=new ne.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(ea).addCommand(ta).addCommand(oa).addCommand(na).addCommand(ra).addCommand(sa);gt();async function aa(){await xn(process.argv);let e=new or.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.51"),e.addCommand(dn),e.addCommand(pn),e.addCommand(fn),e.addCommand(Cn),e.addCommand(Yo),e.addCommand(Kn),e.addCommand(Yn),e.addCommand(go),e.addCommand(Qn),e.addCommand(er),e.addCommand(tr),e.parse(process.argv)}aa().catch(e=>{console.error(e),process.exit(1)});
150
+ Local Sessions:`)),console.log(w.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(w.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(w.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),na=new ne.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,ge.default)("Grouping bot+room into session...").start();try{await oe.default.post(`${pe}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:e.session},{timeout:1e4}),t.succeed(w.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(w.default.red(`Failed to group: ${n}`)),process.exit(1)}}),ra=new ne.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,ge.default)("Adding user to allowlist...").start();try{await oe.default.post(`${pe}/claude-code/allow`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(w.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(w.default.red(`Failed to add user: ${n}`)),process.exit(1)}}),sa=new ne.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,ge.default)("Removing user from allowlist...").start();try{await oe.default.post(`${pe}/claude-code/revoke`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(w.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(w.default.red(`Failed to revoke user: ${n}`)),process.exit(1)}}),tr=new ne.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(ea).addCommand(ta).addCommand(oa).addCommand(na).addCommand(ra).addCommand(sa);gt();async function aa(){await xn(process.argv);let e=new or.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.52"),e.addCommand(dn),e.addCommand(pn),e.addCommand(fn),e.addCommand(Cn),e.addCommand(Yo),e.addCommand(Kn),e.addCommand(Yn),e.addCommand(go),e.addCommand(Qn),e.addCommand(er),e.addCommand(tr),e.parse(process.argv)}aa().catch(e=>{console.error(e),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "badgerclaw",
3
- "version": "0.2.51",
3
+ "version": "0.2.52",
4
4
  "description": "BadgerClaw CLI — one-click bot provisioning",
5
5
  "main": "dist/index.js",
6
6
  "bin": {