badgerclaw 0.2.48 → 0.2.50

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 +37 -35
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var hn=Object.create;var Pe=Object.defineProperty;var wn=Object.getOwnPropertyDescriptor;var yn=Object.getOwnPropertyNames;var _n=Object.getPrototypeOf,bn=Object.prototype.hasOwnProperty;var Sn=(e,t)=>()=>(e&&(t=e(e=0)),t);var $n=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Cn=(e,t)=>{for(var o in t)Pe(e,o,{get:t[o],enumerable:!0})},Ut=(e,t,o,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of yn(t))!bn.call(e,n)&&n!==o&&Pe(e,n,{get:()=>t[n],enumerable:!(s=wn(t,n))||s.enumerable});return e};var c=(e,t,o)=>(o=e!=null?hn(_n(e)):{},Ut(t||!e||!e.__esModule?Pe(o,"default",{value:e,enumerable:!0}):o,e)),Ft=e=>Ut(Pe({},"__esModule",{value:!0}),e);var ee=$n((Ir,jn)=>{jn.exports={name:"badgerclaw",version:"0.2.48",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:'echo "Error: no test specified" && exit 1'},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",typescript:"^5.3.0"}}});var Dt={};Cn(Dt,{getActiveSessions:()=>Ot,launchClaudeCode:()=>Rt,launchMCPServer:()=>At,recordSession:()=>Pt,stopSession:()=>Et});function vt(){try{if(A.default.existsSync(Ct))return JSON.parse(A.default.readFileSync(Ct,"utf-8"))}catch{}return[]}function It(e){A.default.mkdirSync(te,{recursive:!0}),A.default.writeFileSync(Ct,JSON.stringify(e,null,2))}function Ke(e){try{return process.kill(e,0),!0}catch{return!1}}function Qn(){if(process.env.TMUX)return"tmux";try{if((0,U.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),A.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function xt(e,t){let o=O.default.join(te,`claude-launcher-${t}.exp`),s=O.default.join(te,`pending-input-${t}.txt`);A.default.writeFileSync(s,"","utf-8");let n=`#!/usr/bin/expect -f
2
+ "use strict";var _n=Object.create;var De=Object.defineProperty;var bn=Object.getOwnPropertyDescriptor;var Sn=Object.getOwnPropertyNames;var $n=Object.getPrototypeOf,Cn=Object.prototype.hasOwnProperty;var vn=(e,t)=>()=>(e&&(t=e(e=0)),t);var In=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),kn=(e,t)=>{for(var o in t)De(e,o,{get:t[o],enumerable:!0})},Vt=(e,t,o,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Sn(t))!Cn.call(e,n)&&n!==o&&De(e,n,{get:()=>t[n],enumerable:!(s=bn(t,n))||s.enumerable});return e};var i=(e,t,o)=>(o=e!=null?_n($n(e)):{},Vt(t||!e||!e.__esModule?De(o,"default",{value:e,enumerable:!0}):o,e)),qt=e=>Vt(De({},"__esModule",{value:!0}),e);var ne=In((Er,Mn)=>{Mn.exports={name:"badgerclaw",version:"0.2.50",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:'echo "Error: no test specified" && exit 1'},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",typescript:"^5.3.0"}}});var Lt={};kn(Lt,{getActiveSessions:()=>jt,launchClaudeCode:()=>Dt,launchMCPServer:()=>Ot,recordSession:()=>Nt,stopSession:()=>Tt});function At(){try{if(R.default.existsSync(xt))return JSON.parse(R.default.readFileSync(xt,"utf-8"))}catch{}return[]}function Rt(e){R.default.mkdirSync(se,{recursive:!0}),R.default.writeFileSync(xt,JSON.stringify(e,null,2))}function Ze(e){try{return process.kill(e,0),!0}catch{return!1}}function es(){if(process.env.TMUX)return"tmux";try{if((0,G.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),R.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function Pt(e,t){let o=D.default.join(se,`claude-launcher-${t}.exp`),s=D.default.join(se,`pending-input-${t}.txt`);R.default.writeFileSync(s,"","utf-8");let n=`#!/usr/bin/expect -f
3
3
  set timeout -1
4
4
  set msgfile "${s}"
5
5
 
@@ -36,27 +36,27 @@ send "\\r"
36
36
  interact timeout 2 {
37
37
  check_and_send_messages
38
38
  }
39
- `;return A.default.mkdirSync(te,{recursive:!0}),A.default.writeFileSync(o,n,{mode:493}),o}function kt(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function Xn(e,t,o){let s=xt(e,o.BADGERCLAW_SESSION_ID||"default"),n=kt(o),r=`
39
+ `;return R.default.mkdirSync(se,{recursive:!0}),R.default.writeFileSync(o,n,{mode:493}),o}function Et(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function ts(e,t,o){let s=Pt(e,o.BADGERCLAW_SESSION_ID||"default"),n=Et(o),r=`
40
40
  tell application "iTerm"
41
41
  activate
42
42
  set newWindow to (create window with default profile)
43
43
  tell current session of newWindow
44
- write text "cd ${Qe(t)} && ${n} && ${Qe(s)}"
44
+ write text "cd ${et(t)} && ${n} && ${et(s)}"
45
45
  end tell
46
46
  end tell
47
- `;(0,U.execSync)(`osascript -e '${r.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Zn(e,t,o){let s=xt(e,o.BADGERCLAW_SESSION_ID||"default"),n=kt(o),a=`
47
+ `;(0,G.execSync)(`osascript -e '${r.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function os(e,t,o){let s=Pt(e,o.BADGERCLAW_SESSION_ID||"default"),n=Et(o),a=`
48
48
  tell application "Terminal"
49
49
  activate
50
- do script "${`cd ${Qe(t)} && ${n} && ${Qe(s)}`.replace(/"/g,'\\"')}"
50
+ do script "${`cd ${et(t)} && ${n} && ${et(s)}`.replace(/"/g,'\\"')}"
51
51
  end tell
52
- `;(0,U.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function es(e,t,o){let s=xt(e,o.BADGERCLAW_SESSION_ID||"default"),n=kt(o),r=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${n} && ${s}`;(0,U.execSync)(`tmux new-session -d -s ${r} "${a}"`,{stdio:"pipe",timeout:1e4})}function Qe(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function At(e){let t=O.default.join(__dirname,"..","claude-code","mcp-server.js"),o=A.default.existsSync(t)?t:O.default.join(__dirname,"mcp-server.js"),s=(0,U.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 s.unref(),s}function Rt(e){let t=O.default.join(O.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=O.default.join(__dirname,"..","claude-code","mcp-server.js"),s=O.default.join(__dirname,"mcp-server.js"),n=A.default.existsSync(t)?t:A.default.existsSync(o)?o:s,r={BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},a=JSON.stringify({mcpServers:{badgerclaw:{command:"node",args:[n],env:r}}}),i=O.default.join(te,`mcp-config-${e.sessionId}.json`);A.default.mkdirSync(te,{recursive:!0}),A.default.writeFileSync(i,a,"utf-8");let l=`claude --dangerously-skip-permissions --mcp-config ${i}`;switch(Qn()){case"iterm2":Xn(l,e.projectDir,r);break;case"terminal":Zn(l,e.projectDir,r);break;case"tmux":es(l,e.projectDir,r);break;case"direct":(0,U.spawn)(l,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...r},stdio:"ignore",detached:!0}).unref();break}}function Pt(e,t,o,s,n){let r=vt().filter(a=>a.sessionId!==e);r.push({sessionId:e,pid:t,mcpPid:o,port:s,projectDir:n,startedAt:new Date().toISOString()}),It(r)}function Et(e){let t=vt(),o=t.find(n=>n.sessionId===e);if(!o)return!1;if(o.mcpPid&&Ke(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&Ke(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,U.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let s=t.filter(n=>n.sessionId!==e);return It(s),!0}function Ot(){let e=vt(),t=e.filter(o=>Ke(o.mcpPid)||Ke(o.pid));return t.length!==e.length&&It(t),t}var U,A,O,Fo,te,Ct,Xe=Sn(()=>{"use strict";U=require("child_process"),A=c(require("fs")),O=c(require("path")),Fo=c(require("os")),te=O.default.join(Fo.default.homedir(),".badgerclaw"),Ct=O.default.join(te,"claude-sessions.json")});var mn=require("commander");var $o=require("commander"),H=c(require("chalk")),Co=c(require("ora")),vo=c(require("open")),_t=c(require("os"));var at=c(require("crypto"));function Gt(){return at.default.randomBytes(32).toString("base64url")}function Vt(e){return at.default.createHash("sha256").update(e).digest("base64url")}var ge=c(require("fs")),it=c(require("path")),Wt=c(require("os")),qt=it.default.join(Wt.default.homedir(),".badgerclaw"),ct=it.default.join(qt,"auth.json");function h(){try{let e=ge.default.readFileSync(ct,"utf-8");return JSON.parse(e)}catch{return null}}function Ee(e){ge.default.mkdirSync(qt,{recursive:!0}),ge.default.writeFileSync(ct,JSON.stringify(e,null,2),{mode:384})}function pe(){try{ge.default.unlinkSync(ct)}catch{}}function Oe(){let e=h();return e?new Date(e.expires_at)>new Date:!1}function De(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var T=c(require("os")),Ht=c(require("crypto"));function lt(){return Ht.default.createHash("sha256").update(`${T.default.hostname()}-${T.default.platform()}-${T.default.arch()}`).digest("hex").slice(0,16)}function N(){let e=h();if(e?.instance_id)return e.instance_id;let t=lt();return`openclaw-${T.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function Te(){return{hostname:T.default.hostname(),os:T.default.platform(),arch:T.default.arch(),uptimeSeconds:Math.floor(T.default.uptime()),memFreeMb:Math.floor(T.default.freemem()/1024/1024)}}var he=c(require("axios"));var Jt=process.env.BADGERCLAW_ENV==="local",E=process.env.BADGERCLAW_API_URL??(Jt?"http://localhost:8000":"https://api.badger.signout.io"),zt=process.env.BADGERCLAW_AUTH_URL??(Jt?"http://localhost:5500":"https://badgerclaw.ai");var je=E,ae=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},Yt=/account\s+has\s+been\s+(deleted|deactivated)/i,Ne=null,fe=null;function Kt(){return fe}function vn(e){if(!e)return null;let t=e.split(".");if(t.length!==3)return null;try{let o=t[1].replace(/-/g,"+").replace(/_/g,"/"),s=o.length%4===0?o:o+"=".repeat(4-o.length%4),n=JSON.parse(Buffer.from(s,"base64").toString("utf8"));return(typeof n?.sub=="string"?n.sub:null)||null}catch{return null}}async function dt(){let e=h();if(!e?.refresh_token||!e?.email)return fe=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=vn(e.access_token);try{let o=await he.default.post(`${je}/api/v1/user/token/refresh`,{refresh_token:e.refresh_token,email:e.email,...t?{cognito_username:t}:{}}),s=o.data?.result??o.data,n=s?.access_token;if(!n)return fe="server returned no access_token",null;let r=s.expires_in||3600,a=new Date(Date.now()+r*1e3).toISOString();return Ee({...e,access_token:n,expires_at:a}),fe=null,n}catch(o){let s=o?.response?.status,n=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";fe=s?`HTTP ${s}: ${n}`:`network error: ${n}`;let r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(s===403&&Yt.test(r))throw pe(),new ae(r);return null}}function ut(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 Qt(e){return e.interceptors.response.use(void 0,t=>{if(t.response?.status===403){let s=t.message||t.response?.data?.errors?.[0]||t.response?.data?.detail||"";if(Yt.test(s))return pe(),Promise.reject(new ae(s))}return Promise.reject(t)}),e}function Xt(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,Ne||(Ne=dt().finally(()=>{Ne=null}));let s=await Ne;return s?(o.headers.Authorization=`Bearer ${s}`,e.request(o)):Promise.reject(t)}),e}function I(){let e=h(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=he.default.create({baseURL:je,headers:t});return ut(o),Xt(o),Qt(o),o}function Zt(){return ut(he.default.create({baseURL:je,headers:{"Content-Type":"application/json"}}))}function Le(e){let t=he.default.create({baseURL:je,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return ut(t),Xt(t),Qt(t),t}var co=require("commander"),j=c(require("chalk")),pt=c(require("ora")),lo=c(require("os")),ft=c(require("path")),we=c(require("fs"));var W=c(require("fs")),eo=c(require("os")),gt=c(require("path")),K=gt.default.join(eo.default.homedir(),".openclaw","openclaw.json.lock"),to=1e4,oo=50,In=Math.ceil(to/oo);function no(){try{let e=W.default.statSync(K);return Date.now()-e.mtimeMs>to}catch{return!0}}function mt(){try{return W.default.mkdirSync(gt.default.dirname(K),{recursive:!0}),W.default.writeFileSync(K,String(process.pid),{flag:"wx"}),!0}catch{if(no())try{return W.default.unlinkSync(K),W.default.writeFileSync(K,String(process.pid),{flag:"wx"}),!0}catch{return!1}return!1}}function so(){try{W.default.unlinkSync(K)}catch{}}async function ro(e){let t=!1;for(let o=0;o<In;o++){if(mt()){t=!0;break}await new Promise(s=>setTimeout(s,oo))}t||console.warn("[config-lock] Could not acquire lock after timeout \u2014 proceeding without lock");try{return await e()}finally{t&&so()}}function Q(e){let t=mt();if(!t&&no()){try{W.default.unlinkSync(K)}catch{}t=mt()}try{return e()}finally{t&&so()}}var ao=ft.default.join(lo.default.homedir(),".openclaw","openclaw.json");function Be(e){return`'${e.replace(/'/g,"'\\''")}'`}var q=null;function xn(){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(we.default.existsSync(t))return q=`${Be(process.execPath)} ${Be(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 s=ft.default.join(o,"openclaw","openclaw.mjs");if(we.default.existsSync(s))return q=`${Be(process.execPath)} ${Be(s)}`,q}}catch{}return q="openclaw",q}function io(e,t,o){t?t.fail(j.default.red(o)):e&&console.error(`[autopair] ${o}`)}async function ye(e,t,o,s){let n=h();if(!n)return;let r=s?null:(0,pt.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${E}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e,instance_id:N()})});if(!a.ok){if(a.status===410){r?.info(j.default.dim(`${t} already paired (race-loss; another channel redeemed first).`));return}let y=await a.json().catch(()=>({errors:[a.statusText]}));io(s,r,`Failed to redeem ${t}: ${y.errors?.[0]||a.status}`);return}let i=await a.json(),l=i.result??i;await ro(async()=>{let y=l.user_id.split(":")[0].replace("@","").replace(/_bot$/,""),_;try{_=JSON.parse(we.default.readFileSync(ao,"utf-8"))}catch{_={}}_.channels||(_.channels={}),_.channels.badgerclaw||(_.channels.badgerclaw={}),_.channels.badgerclaw.accounts||(_.channels.badgerclaw.accounts={});let S={userId:l.user_id,accessToken:l.access_token,homeserver:l.homeserver,encryption:!0,groupPolicy:"open",allowlistOnly:!1,dm:{policy:"open"}};l.device_id&&(S.deviceId=l.device_id),_.channels.badgerclaw.accounts[y]=S,we.default.writeFileSync(ao,JSON.stringify(_,null,2),{mode:384})}),await fetch(`${E}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${n.access_token}`}}).catch(()=>{}),r?.succeed(j.default.green(`\u2705 ${l.bot_name} (${l.user_id}) paired \u2014 bot is live!`))}catch(a){io(s,r,`Failed to pair ${t}: ${a.message}`)}}async function _e(e=!1){let t=h();if(!t)return 0;let o=Le(t.access_token);try{let{data:s}=await o.get("/api/v1/openclaw/pending-pairs");if(!s||s.length===0)return 0;let n=new Map;for(let a of s)n.set(a.bot_user_id,a);for(let a of s)n.get(a.bot_user_id)!==a&&await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{});let r=0;for(let a of n.values()){let i=e?null:(0,pt.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await ye(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),r++}catch(l){i?.fail(j.default.red(`Error pairing ${a.bot_name}: ${l}`))}}if(r>0)try{let{execSync:a}=await import("child_process");a(`${xn()} gateway restart`,{stdio:"ignore"}),e||console.log(j.default.green(`
53
- \u26A1 ${r} 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(j.default.yellow(`
54
- \u26A1 ${r} bot(s) paired. Run: openclaw gateway restart`))}return r}catch{return 0}}var uo=new co.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!h()){console.log(j.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(j.default.dim("Checking for pending bot pairs...")),await _e(!1)===0&&console.log(j.default.dim("No pending pairs found."))});var wo=c(require("os"));var Me=c(require("fs")),X=c(require("path")),be=c(require("os")),Se=require("child_process"),mo="ai.badgerclaw.watch",go=X.default.join(be.default.homedir(),"Library","LaunchAgents"),ht=X.default.join(go,`${mo}.plist`);function kn(){try{return(0,Se.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function An(){try{return(0,Se.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function Rn(e){let t=X.default.join(be.default.homedir(),".badgerclaw"),o=An(),s=X.default.dirname(o),n=X.default.dirname(e),r=[s,n,"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"],a=new Set,i=r.filter(l=>!l||a.has(l)?!1:(a.add(l),!0)).join(":");return`<?xml version="1.0" encoding="UTF-8"?>
52
+ `;(0,G.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function ns(e,t,o){let s=Pt(e,o.BADGERCLAW_SESSION_ID||"default"),n=Et(o),r=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${n} && ${s}`;(0,G.execSync)(`tmux new-session -d -s ${r} "${a}"`,{stdio:"pipe",timeout:1e4})}function et(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Ot(e){let t=D.default.join(__dirname,"..","claude-code","mcp-server.js"),o=R.default.existsSync(t)?t:D.default.join(__dirname,"mcp-server.js"),s=(0,G.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 s.unref(),s}function Dt(e){let t=D.default.join(D.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=D.default.join(__dirname,"..","claude-code","mcp-server.js"),s=D.default.join(__dirname,"mcp-server.js"),n=R.default.existsSync(t)?t:R.default.existsSync(o)?o:s,r={BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},a=JSON.stringify({mcpServers:{badgerclaw:{command:"node",args:[n],env:r}}}),c=D.default.join(se,`mcp-config-${e.sessionId}.json`);R.default.mkdirSync(se,{recursive:!0}),R.default.writeFileSync(c,a,"utf-8");let l=`claude --dangerously-skip-permissions --mcp-config ${c}`;switch(es()){case"iterm2":ts(l,e.projectDir,r);break;case"terminal":os(l,e.projectDir,r);break;case"tmux":ns(l,e.projectDir,r);break;case"direct":(0,G.spawn)(l,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...r},stdio:"ignore",detached:!0}).unref();break}}function Nt(e,t,o,s,n){let r=At().filter(a=>a.sessionId!==e);r.push({sessionId:e,pid:t,mcpPid:o,port:s,projectDir:n,startedAt:new Date().toISOString()}),Rt(r)}function Tt(e){let t=At(),o=t.find(n=>n.sessionId===e);if(!o)return!1;if(o.mcpPid&&Ze(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&Ze(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,G.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let s=t.filter(n=>n.sessionId!==e);return Rt(s),!0}function jt(){let e=At(),t=e.filter(o=>Ze(o.mcpPid)||Ze(o.pid));return t.length!==e.length&&Rt(t),t}var G,R,D,Vo,se,xt,tt=vn(()=>{"use strict";G=require("child_process"),R=i(require("fs")),D=i(require("path")),Vo=i(require("os")),se=D.default.join(Vo.default.homedir(),".badgerclaw"),xt=D.default.join(se,"claude-sessions.json")});var fn=require("commander");var ko=require("commander"),z=i(require("chalk")),xo=i(require("ora")),Ao=i(require("open")),$t=i(require("os"));var lt=i(require("crypto"));function Ht(){return lt.default.randomBytes(32).toString("base64url")}function Jt(e){return lt.default.createHash("sha256").update(e).digest("base64url")}var he=i(require("fs")),dt=i(require("path")),zt=i(require("os")),Kt=dt.default.join(zt.default.homedir(),".badgerclaw"),ut=dt.default.join(Kt,"auth.json");function _(){try{let e=he.default.readFileSync(ut,"utf-8");return JSON.parse(e)}catch{return null}}function Ne(e){he.default.mkdirSync(Kt,{recursive:!0}),he.default.writeFileSync(ut,JSON.stringify(e,null,2),{mode:384})}function we(){try{he.default.unlinkSync(ut)}catch{}}function Te(){let e=_();return e?new Date(e.expires_at)>new Date:!1}function je(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var T=i(require("os")),Yt=i(require("crypto"));function mt(){return Yt.default.createHash("sha256").update(`${T.default.hostname()}-${T.default.platform()}-${T.default.arch()}`).digest("hex").slice(0,16)}function j(){let e=_();if(e?.instance_id)return e.instance_id;let t=mt();return`openclaw-${T.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function Le(){return{hostname:T.default.hostname(),os:T.default.platform(),arch:T.default.arch(),uptimeSeconds:Math.floor(T.default.uptime()),memFreeMb:Math.floor(T.default.freemem()/1024/1024)}}var _e=i(require("axios"));var Qt=process.env.BADGERCLAW_ENV==="local",O=process.env.BADGERCLAW_API_URL??(Qt?"http://localhost:8000":"https://api.badger.signout.io"),Xt=process.env.BADGERCLAW_AUTH_URL??(Qt?"http://localhost:5500":"https://badgerclaw.ai");var Me=O,le=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},Zt=/account\s+has\s+been\s+(deleted|deactivated)/i,Be=null,ye=null;function eo(){return ye}function xn(e){if(!e)return null;let t=e.split(".");if(t.length!==3)return null;try{let o=t[1].replace(/-/g,"+").replace(/_/g,"/"),s=o.length%4===0?o:o+"=".repeat(4-o.length%4),n=JSON.parse(Buffer.from(s,"base64").toString("utf8"));return(typeof n?.sub=="string"?n.sub:null)||null}catch{return null}}async function gt(){let e=_();if(!e?.refresh_token||!e?.email)return ye=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=xn(e.access_token);try{let o=await _e.default.post(`${Me}/api/v1/user/token/refresh`,{refresh_token:e.refresh_token,email:e.email,...t?{cognito_username:t}:{}}),s=o.data?.result??o.data,n=s?.access_token;if(!n)return ye="server returned no access_token",null;let r=s.expires_in||3600,a=new Date(Date.now()+r*1e3).toISOString();return Ne({...e,access_token:n,expires_at:a}),ye=null,n}catch(o){let s=o?.response?.status,n=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";ye=s?`HTTP ${s}: ${n}`:`network error: ${n}`;let r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(s===403&&Zt.test(r))throw we(),new le(r);return null}}function pt(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 to(e){return e.interceptors.response.use(void 0,t=>{if(t.response?.status===403){let s=t.message||t.response?.data?.errors?.[0]||t.response?.data?.detail||"";if(Zt.test(s))return we(),Promise.reject(new le(s))}return Promise.reject(t)}),e}function oo(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,Be||(Be=gt().finally(()=>{Be=null}));let s=await Be;return s?(o.headers.Authorization=`Bearer ${s}`,e.request(o)):Promise.reject(t)}),e}function k(){let e=_(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=_e.default.create({baseURL:Me,headers:t});return pt(o),oo(o),to(o),o}function no(){return pt(_e.default.create({baseURL:Me,headers:{"Content-Type":"application/json"}}))}function Fe(e){let t=_e.default.create({baseURL:Me,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return pt(t),oo(t),to(t),t}var go=require("commander"),L=i(require("chalk")),wt=i(require("ora")),po=i(require("os")),yt=i(require("path")),be=i(require("fs"));var H=i(require("fs")),so=i(require("os")),ht=i(require("path")),Z=ht.default.join(so.default.homedir(),".openclaw","openclaw.json.lock"),ro=1e4,ao=50,An=Math.ceil(ro/ao);function io(){try{let e=H.default.statSync(Z);return Date.now()-e.mtimeMs>ro}catch{return!0}}function ft(){try{return H.default.mkdirSync(ht.default.dirname(Z),{recursive:!0}),H.default.writeFileSync(Z,String(process.pid),{flag:"wx"}),!0}catch{if(io())try{return H.default.unlinkSync(Z),H.default.writeFileSync(Z,String(process.pid),{flag:"wx"}),!0}catch{return!1}return!1}}function co(){try{H.default.unlinkSync(Z)}catch{}}async function lo(e){let t=!1;for(let o=0;o<An;o++){if(ft()){t=!0;break}await new Promise(s=>setTimeout(s,ao))}t||console.warn("[config-lock] Could not acquire lock after timeout \u2014 proceeding without lock");try{return await e()}finally{t&&co()}}function ee(e){let t=ft();if(!t&&io()){try{H.default.unlinkSync(Z)}catch{}t=ft()}try{return e()}finally{t&&co()}}var uo=yt.default.join(po.default.homedir(),".openclaw","openclaw.json");function Ue(e){return`'${e.replace(/'/g,"'\\''")}'`}var J=null;function Rn(){if(J!==null)return J;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(be.default.existsSync(t))return J=`${Ue(process.execPath)} ${Ue(t)}`,J;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 s=yt.default.join(o,"openclaw","openclaw.mjs");if(be.default.existsSync(s))return J=`${Ue(process.execPath)} ${Ue(s)}`,J}}catch{}return J="openclaw",J}function mo(e,t,o){t?t.fail(L.default.red(o)):e&&console.error(`[autopair] ${o}`)}async function Se(e,t,o,s){let n=_();if(!n)return;let r=s?null:(0,wt.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${O}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e,instance_id:j()})});if(!a.ok){if(a.status===410){r?.info(L.default.dim(`${t} already paired (race-loss; another channel redeemed first).`));return}let m=await a.json().catch(()=>({errors:[a.statusText]}));mo(s,r,`Failed to redeem ${t}: ${m.errors?.[0]||a.status}`);return}let c=await a.json(),l=c.result??c;await lo(async()=>{let m=l.user_id.split(":")[0].replace("@","").replace(/_bot$/,""),d;try{d=JSON.parse(be.default.readFileSync(uo,"utf-8"))}catch{d={}}d.channels||(d.channels={}),d.channels.badgerclaw||(d.channels.badgerclaw={}),d.channels.badgerclaw.accounts||(d.channels.badgerclaw.accounts={});let f={userId:l.user_id,accessToken:l.access_token,homeserver:l.homeserver,encryption:!0,groupPolicy:"open",allowlistOnly:!1,dm:{policy:"open"}};l.device_id&&(f.deviceId=l.device_id),d.channels.badgerclaw.accounts[m]=f,be.default.writeFileSync(uo,JSON.stringify(d,null,2),{mode:384})}),await fetch(`${O}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${n.access_token}`}}).catch(()=>{}),r?.succeed(L.default.green(`\u2705 ${l.bot_name} (${l.user_id}) paired \u2014 bot is live!`))}catch(a){mo(s,r,`Failed to pair ${t}: ${a.message}`)}}async function $e(e=!1){let t=_();if(!t)return 0;let o=Fe(t.access_token);try{let{data:s}=await o.get("/api/v1/openclaw/pending-pairs");if(!s||s.length===0)return 0;let n=new Map;for(let a of s)n.set(a.bot_user_id,a);for(let a of s)n.get(a.bot_user_id)!==a&&await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{});let r=0;for(let a of n.values()){let c=e?null:(0,wt.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await Se(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),r++}catch(l){c?.fail(L.default.red(`Error pairing ${a.bot_name}: ${l}`))}}if(r>0)try{let{execSync:a}=await import("child_process");a(`${Rn()} gateway restart`,{stdio:"ignore"}),e||console.log(L.default.green(`
53
+ \u26A1 ${r} 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(L.default.yellow(`
54
+ \u26A1 ${r} bot(s) paired. Run: openclaw gateway restart`))}return r}catch{return 0}}var fo=new go.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!_()){console.log(L.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(L.default.dim("Checking for pending bot pairs...")),await $e(!1)===0&&console.log(L.default.dim("No pending pairs found."))});var So=i(require("os"));var Ge=i(require("fs")),te=i(require("path")),Ce=i(require("os")),ve=require("child_process"),ho="ai.badgerclaw.watch",wo=te.default.join(Ce.default.homedir(),"Library","LaunchAgents"),_t=te.default.join(wo,`${ho}.plist`);function Pn(){try{return(0,ve.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function En(){try{return(0,ve.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function On(e){let t=te.default.join(Ce.default.homedir(),".badgerclaw"),o=En(),s=te.default.dirname(o),n=te.default.dirname(e),r=[s,n,"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"],a=new Set,c=r.filter(l=>!l||a.has(l)?!1:(a.add(l),!0)).join(":");return`<?xml version="1.0" encoding="UTF-8"?>
55
55
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
56
56
  <plist version="1.0">
57
57
  <dict>
58
58
  <key>Label</key>
59
- <string>${mo}</string>
59
+ <string>${ho}</string>
60
60
  <key>ProgramArguments</key>
61
61
  <array>
62
62
  <string>${o}</string>
@@ -66,7 +66,7 @@ interact timeout 2 {
66
66
  <key>EnvironmentVariables</key>
67
67
  <dict>
68
68
  <key>PATH</key>
69
- <string>${i}</string>
69
+ <string>${c}</string>
70
70
  </dict>
71
71
  <key>RunAtLoad</key>
72
72
  <true/>
@@ -79,7 +79,7 @@ interact timeout 2 {
79
79
  <key>ThrottleInterval</key>
80
80
  <integer>30</integer>
81
81
  </dict>
82
- </plist>`}function po(){if(be.default.platform()==="darwin")try{let e=kn();Me.default.mkdirSync(go,{recursive:!0}),Me.default.mkdirSync(X.default.join(be.default.homedir(),".badgerclaw"),{recursive:!0}),Me.default.writeFileSync(ht,Rn(e));try{(0,Se.execSync)(`launchctl unload "${ht}" 2>/dev/null`)}catch{}(0,Se.execSync)(`launchctl load "${ht}"`),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 Ue=c(require("fs")),$e=c(require("path")),Fe=c(require("os")),B=require("child_process"),wt="badgerclaw-watch.service",fo=$e.default.join(Fe.default.homedir(),".config","systemd","user"),Pn=$e.default.join(fo,wt);function En(){try{return(0,B.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function On(){try{return(0,B.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function Dn(e){let t=On(),o=$e.default.dirname(t);return`[Unit]
82
+ </plist>`}function yo(){if(Ce.default.platform()==="darwin")try{let e=Pn();Ge.default.mkdirSync(wo,{recursive:!0}),Ge.default.mkdirSync(te.default.join(Ce.default.homedir(),".badgerclaw"),{recursive:!0}),Ge.default.writeFileSync(_t,On(e));try{(0,ve.execSync)(`launchctl unload "${_t}" 2>/dev/null`)}catch{}(0,ve.execSync)(`launchctl load "${_t}"`),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 We=i(require("fs")),Ie=i(require("path")),Ve=i(require("os")),F=require("child_process"),bt="badgerclaw-watch.service",_o=Ie.default.join(Ve.default.homedir(),".config","systemd","user"),Dn=Ie.default.join(_o,bt);function Nn(){try{return(0,F.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function Tn(){try{return(0,F.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function jn(e){let t=Tn(),o=Ie.default.dirname(t);return`[Unit]
83
83
  Description=BadgerClaw background watcher (heartbeat + pair events)
84
84
  After=network-online.target
85
85
  Wants=network-online.target
@@ -95,11 +95,11 @@ StandardError=append:%h/.badgerclaw/heartbeat.log
95
95
 
96
96
  [Install]
97
97
  WantedBy=default.target
98
- `}function Tn(){try{return(0,B.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function ho(){if(Fe.default.platform()==="linux"){if(!Tn()){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=En();Ue.default.mkdirSync(fo,{recursive:!0}),Ue.default.mkdirSync($e.default.join(Fe.default.homedir(),".badgerclaw"),{recursive:!0}),Ue.default.writeFileSync(Pn,Dn(e)),(0,B.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,B.execSync)(`systemctl --user restart ${wt}`,{stdio:"ignore"})}catch{}(0,B.execSync)(`systemctl --user enable --now ${wt}`,{stdio:"ignore"});try{let t=(0,B.execSync)("whoami",{encoding:"utf-8"}).trim();(0,B.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 yo(){let e=wo.default.platform();if(e==="darwin")return po();if(e==="linux")return ho();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var yt=c(require("fs")),bo=c(require("os")),So=c(require("path")),Z=require("child_process"),M=c(require("chalk"));var _o=So.default.join(bo.default.homedir(),".openclaw","openclaw.json");function Nn(e=!1){let t=null;try{yt.default.existsSync(_o)&&(t=JSON.parse(yt.default.readFileSync(_o,"utf-8"))?.gateway?.mode??null)}catch{}if(typeof t=="string"&&t.length>0)return!0;e||console.log(M.default.dim(" Setting gateway.mode=local..."));try{return Q(()=>((0,Z.execSync)("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),!0))}catch(o){return e||(console.log(M.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${o.message}`)),console.log(M.default.yellow(" Run `openclaw config set gateway.mode local` manually."))),!1}}function Ge(e={}){let t=e.verbose!==!1,o=a=>{t&&console.log(a)};o(M.default.dim(" Installing OpenClaw gateway service (if not present)...")),(0,Z.spawnSync)("openclaw",["gateway","install"],{stdio:t?"inherit":"pipe",shell:!0}).status!==0&&o(M.default.yellow(" \u26A0\uFE0F `openclaw gateway install` returned non-zero \u2014 continuing.")),Nn(!t),o(M.default.dim(" Starting OpenClaw gateway..."));let n=(0,Z.spawnSync)("openclaw",["gateway","start"],{stdio:t?"inherit":"pipe",shell:!0}),r="started";return n.status!==0&&(n=(0,Z.spawnSync)("openclaw",["gateway","restart"],{stdio:t?"inherit":"pipe",shell:!0}),r="restarted"),n.status!==0?{ok:!1,error:"gateway start/restart returned non-zero exit"}:{ok:!0,state:r}}function Ve(){if(process.platform!=="linux"||process.getuid?.()!==0)return;let e=(0,Z.spawnSync)("loginctl",["show-user","root","--property=Linger"],{encoding:"utf-8"});e.status===0&&/Linger=no/.test(e.stdout||"")&&(console.log(M.default.yellow(`
99
- \u26A0\uFE0F systemd lingering is OFF for root. The gateway will stop on SSH disconnect.`)),console.log(M.default.dim(" Enable persistence: loginctl enable-linger root")))}var Ln=2e3,Bn=12e4,Io=new $o.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=Gt(),t=Vt(e),o=`${zt}/cli-auth?code=${t}`;console.log(H.default.yellow("Opening browser for authentication...")),console.log(H.default.dim(`If the browser doesn't open, visit: ${o}`)),await(0,vo.default)(o);let s=(0,Co.default)("Waiting for authentication...").start(),n=Zt(),r=Date.now();for(;Date.now()-r<Bn;){try{let a=await n.post(`/api/v1/openclaw/cli/auth/poll/${t}`,{code_verifier:e,code_challenge:t});if(a.status===429){await new Promise(i=>setTimeout(i,5e3));continue}if(a.data?.access_token){let{access_token:i,user_id:l,expires_at:y,refresh_token:_,email:S}=a.data,se=lt(),G=`openclaw-${_t.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${se}`,V=G;try{let{version:k}=ee(),re=await n.post("/api/v1/openclaw/register",{instance_id:G,label:_t.default.hostname(),version:k,machine_fingerprint:se},{headers:{Authorization:`Bearer ${i}`}}),L=re.data?.result||re.data;L&&typeof L.instance_id=="string"&&L.instance_id.length>0&&(V=L.instance_id)}catch(k){let re=k?.response?.status;if(re===403||re===409){let L=k?.response?.data,gn=Array.isArray(L?.errors)&&typeof L.errors[0]=="string"?L.errors[0]:null,rt=L?.detail,pn=typeof rt=="string"?rt:rt?.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,fn=gn||pn||`Login refused (status ${re}). Open the BadgerClaw app to check your subscription state.`;s.fail(H.default.red(fn)),process.exit(1)}}Ee({access_token:i,user_id:l,instance_id:V,expires_at:y,refresh_token:_,email:S}),s.succeed(H.default.green(`Logged in as ${De(l)}`)),Ge({verbose:!0}).ok||console.log(H.default.yellow("\n \u26A0\uFE0F Logged in, but gateway failed to start. Re-run `badgerclaw setup` to repair."));let x=await _e(!0);x>0&&console.log(H.default.green(`\u2705 ${x} bot(s) automatically paired to OpenClaw.`)),yo(),Ve();return}}catch{}await new Promise(a=>setTimeout(a,Ln))}s.fail(H.default.red("Authentication timed out. Please try again.")),process.exit(1)});var ko=require("commander"),Ce=c(require("chalk")),We=c(require("fs")),ie=c(require("os")),Ie=c(require("path")),ve=require("child_process");function Mn(){let e=process.platform;if(e==="darwin"){let t=Ie.default.join(ie.default.homedir(),"Library","LaunchAgents","ai.badgerclaw.watch.plist");(0,ve.spawnSync)("launchctl",["unload",t],{stdio:"ignore"});try{We.default.unlinkSync(t)}catch{}}else if(e==="linux"){(0,ve.spawnSync)("systemctl",["--user","disable","--now","badgerclaw-watch.service"],{stdio:"ignore"});let t=Ie.default.join(ie.default.homedir(),".config","systemd","user","badgerclaw-watch.service");try{We.default.unlinkSync(t)}catch{}(0,ve.spawnSync)("systemctl",["--user","daemon-reload"],{stdio:"ignore"})}(0,ve.spawnSync)("pkill",["-f","badgerclaw heartbeat"],{stdio:"ignore"})}function xo(e){try{return We.default.rmSync(e,{recursive:!0,force:!0}),!0}catch{return!1}}var Ao=new ko.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=h();if(t)try{let a=Le(t.access_token),{version:i}=ee();await a.post("/api/v1/openclaw/register",{instance_id:t.instance_id,label:ie.default.hostname(),version:i,online:!1})}catch{}if(Mn(),e.keepState){pe(),console.log(Ce.default.green("Logged out \u2014 auth cleared. (state preserved with --keep-state)"));return}let o=Ie.default.join(ie.default.homedir(),".badgerclaw"),s=xo(o),n=Ie.default.join(ie.default.homedir(),".openclaw","badgerclaw"),r=xo(n);s||r?(console.log(Ce.default.green("Logged out \u2014 local state cleared.")),console.log(Ce.default.dim(` Removed: ${o}${r?`, ${n}`:""}`))):console.log(Ce.default.green("Logged out."))});var Ro=require("commander"),bt=c(require("chalk"));var Po=new Ro.Command("status").description("Show connected instance info").action(async()=>{let e=h();(!e||!Oe())&&(console.log(bt.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(bt.default.green("Authenticated")),console.log(` User: ${De(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var le=require("commander"),f=c(require("chalk")),ze=c(require("ora")),Je=c(require("fs")),To=c(require("os")),No=c(require("path")),jo=require("child_process");var ce=c(require("fs")),Eo=c(require("os")),Oo=c(require("path")),Do=require("child_process");function qe(e){let t=e.split(":")[0].replace(/^@/,"").replace(/_bot$/,""),o=Oo.join(Eo.homedir(),".openclaw","openclaw.json");return ce.existsSync(o)?{changed:Q(()=>{let n=JSON.parse(ce.readFileSync(o,"utf-8")),r=!1;if(n.channels?.badgerclaw?.accounts?.[t]&&(delete n.channels.badgerclaw.accounts[t],r=!0),n.agents?.list){let a=n.agents.list.length;n.agents.list=n.agents.list.filter(i=>i.id!==t),n.agents.list.length!==a&&(r=!0)}return r&&ce.writeFileSync(o,JSON.stringify(n,null,2)),r})}:{changed:!1}}function He(){try{return(0,Do.execSync)("openclaw gateway restart",{stdio:"ignore"}),!0}catch{return!1}}function St(){Oe()||(console.log(f.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function Un(e){return/^[a-z0-9_]{4,20}$/.test(e)}function Lo(e){return e.replace(/_bot$/,"")}var Fn=new le.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").action(async e=>{St(),Un(e)||(console.log(f.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let t=(0,ze.default)(`Creating bot "${e}"...`).start();try{await I().post("/api/v1/openclaw/bots",{username:e}),t.succeed(f.default.green(`Bot "${e}" created successfully!`))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(f.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),Gn=new le.Command("list").description("List your bots").action(async()=>{St();let e=(0,ze.default)("Fetching bots...").start();try{let s=(await I().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),s.length===0){console.log(f.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(f.default.green(`Your bots (${s.length}):
100
- `));for(let n of s){let r=Lo(n.username||n.name),a=n.active===!1?f.default.dim("deactivated"):n.openclaw_connected?f.default.green("connected"):f.default.gray("disconnected");console.log(` ${f.default.bold(r)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(f.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),Vn=new le.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{St();let t=(0,ze.default)(`Deactivating bot "${e}"...`).start();try{await I().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(f.default.green(`Bot "${e}" deactivated.`));let{changed:s}=qe(e);s&&(console.log(f.default.dim(" Removed from openclaw.json")),He()&&console.log(f.default.dim(" Gateway restarted")))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(f.default.red(`Failed to deactivate bot: ${s}`)),process.exit(1)}});function Wn(e){let t=e.trim();return t.startsWith("@")&&(t=t.slice(1)),t.includes(":")&&(t=t.split(":")[0]),Lo(t)}function qn(e){let t=e.replace(/[^a-zA-Z0-9_.-]/g,"_")||"default";return No.default.join(To.default.homedir(),".openclaw","badgerclaw","quarantine",`${t}.json`)}var Hn=new le.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=Wn(e);t||(console.log(f.default.red(`Couldn't parse bot name "${e}".`)),process.exit(1));let o=qn(t),s=!1;if(Je.default.existsSync(o))try{let n=JSON.parse(Je.default.readFileSync(o,"utf-8")),r=n.failureCount??"?",a=n.quarantinedAt??"?";console.log(f.default.dim(` Quarantine for "${t}" \u2014 ${r} failures, since ${a}`)),Je.default.unlinkSync(o),s=!0}catch(n){console.log(f.default.red(`Failed to clear quarantine ledger at ${o}: ${n.message}`)),process.exit(1)}console.log(s?f.default.green(`\u2705 Cleared quarantine for "${t}"`):f.default.dim(` No quarantine file for "${t}" \u2014 already healthy or never quarantined.`)),console.log(f.default.dim(" Restarting OpenClaw gateway so the refresh chain runs..."));try{(0,jo.execSync)("openclaw gateway restart",{stdio:"inherit"})}catch(n){console.log(f.default.yellow(` Gateway restart command failed: ${n.message}`)),console.log(f.default.yellow(" Run `openclaw gateway restart` manually.")),process.exit(1)}console.log(f.default.green(`
101
- \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(f.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(f.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(f.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(f.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),Bo=new le.Command("bot").description("Manage bots").addCommand(Fn).addCommand(Gn).addCommand(Vn).addCommand(Hn);var Qo=require("commander"),g=c(require("chalk"));var Ye=c(require("axios")),Jn=7331,Mo=`http://localhost:${Jn}`,zn=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,Yn=`http://127.0.0.1:${zn}`,$t="unknown";async function Kn(){try{return await Ye.default.get(Yn,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function xe(){try{let t=(await Ye.default.get(`${Mo}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&($t=t.pluginVersion),t}catch{return{status:await Kn()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:$t,bots:[]}}}function Uo(e){e&&e!=="unknown"&&($t=e)}async function de(){try{return{success:!0,message:(await Ye.default.post(`${Mo}/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 qo=require("commander"),d=c(require("chalk")),Ho=c(require("axios"));var C=require("child_process"),m=c(require("fs")),b=c(require("path")),ue=c(require("os")),R=c(require("axios"));async function F(e){return e.command_type==="update_cli"?os(e.payload?.target_version):e.command_type==="update_plugin"?ns(e.payload?.target_version):e.command_type==="restart_gateway"?ts():e.command_type==="leave_room"?ws(e.payload):e.command_type==="start_claude_code"?cs(e.payload):e.command_type==="stop_claude_code"?ls(e.payload):e.command_type==="start_claude_control"?ds(e.payload):e.command_type==="stop_claude_control"?us(e.payload):e.command_type==="update_claude_tools"?ms(e.payload):e.command_type==="bot_share_notify"?gs(e.payload):e.command_type==="bot_share_revoked"?ps(e.payload):e.command_type==="bot_share_expired"?fs(e.payload):e.command_type==="bot_refresh"?hs(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function ts(){try{return(0,C.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,C.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 os(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,C.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,C.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),n=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return rs(),{success:!0,message:`Updated CLI to ${n}`,newVersion:n}}catch(o){let s=o.stderr?.toString()||o.message||"Unknown error";return s.includes("EACCES")||s.includes("permission")?{success:!1,message:"Permission denied. Run: sudo npm install -g badgerclaw"}:{success:!1,message:`CLI update failed: ${s.slice(0,500)}`}}}async function ns(e){let t=b.default.join(ue.default.homedir(),".openclaw","extensions","badgerclaw");if(!m.default.existsSync(t))return{success:!1,message:"Cannot find plugin directory (~/.openclaw/extensions/badgerclaw). Re-run: badgerclaw setup"};let o=e?`@badgerclaw/connect@${e}`:"@badgerclaw/connect@latest";try{(0,C.execSync)(`npm install ${o}`,{cwd:t,stdio:"pipe",timeout:12e4});let s=b.default.join(t,"node_modules","@badgerclaw","connect"),n=b.default.join(s,"package.json"),r="unknown";m.default.existsSync(n)&&(r=JSON.parse(m.default.readFileSync(n,"utf-8")).version||"unknown"),Uo(r),ss(s,t);let a=b.default.join(t,"package.json");if(m.default.existsSync(a)&&m.default.existsSync(n))try{let i=JSON.parse(m.default.readFileSync(a,"utf-8")),l=JSON.parse(m.default.readFileSync(n,"utf-8"));i.version=r,l.openclaw&&(i.openclaw={...i.openclaw,...l.openclaw}),m.default.writeFileSync(a,JSON.stringify(i,null,2)+`
102
- `)}catch{}try{(0,C.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}for(let i=0;i<15;i++){await new Promise(l=>setTimeout(l,1e3));try{let l=await R.default.get("http://localhost:7331/health",{timeout:3e3});if(l.data?.status==="running"&&l.data?.pluginVersion===r)break}catch{}}return{success:!0,message:`Updated plugin to ${r}, gateway restarted`,newVersion:r}}catch(s){return{success:!1,message:`Plugin update failed: ${(s.stderr?.toString()||s.message||"").slice(0,500)}`}}}function ss(e,t){let o=b.default.join(e,"dist"),s=b.default.join(t,"dist");m.default.existsSync(o)&&(m.default.mkdirSync(s,{recursive:!0}),Tt(o,s));let n=b.default.join(e,"openclaw.plugin.json");m.default.existsSync(n)&&m.default.copyFileSync(n,b.default.join(t,"openclaw.plugin.json"));let r=b.default.join(e,"scripts"),a=b.default.join(t,"scripts");m.default.existsSync(r)&&(m.default.mkdirSync(a,{recursive:!0}),Tt(r,a));for(let i of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let l=b.default.join(t,i);m.default.existsSync(l)&&(m.default.statSync(l).isDirectory()?m.default.rmSync(l,{recursive:!0,force:!0}):m.default.unlinkSync(l))}}function Tt(e,t){for(let o of m.default.readdirSync(e,{withFileTypes:!0})){let s=b.default.join(e,o.name),n=b.default.join(t,o.name);o.isDirectory()?(m.default.mkdirSync(n,{recursive:!0}),Tt(s,n)):m.default.copyFileSync(s,n)}}function rs(){try{try{(0,C.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,C.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,C.execSync)("sleep 1",{stdio:"pipe"});let e=(0,C.execSync)("which badgerclaw",{stdio:"pipe"}).toString().trim();(0,C.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,C.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function as(){let e=b.default.join(ue.default.homedir(),".badgerclaw","workspace");m.default.mkdirSync(e,{recursive:!0});let t=b.default.join(e,".git");return m.default.existsSync(t)||(0,C.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),m.default.writeFileSync(b.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
98
+ `}function Ln(){try{return(0,F.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function bo(){if(Ve.default.platform()==="linux"){if(!Ln()){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=Nn();We.default.mkdirSync(_o,{recursive:!0}),We.default.mkdirSync(Ie.default.join(Ve.default.homedir(),".badgerclaw"),{recursive:!0}),We.default.writeFileSync(Dn,jn(e)),(0,F.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,F.execSync)(`systemctl --user restart ${bt}`,{stdio:"ignore"})}catch{}(0,F.execSync)(`systemctl --user enable --now ${bt}`,{stdio:"ignore"});try{let t=(0,F.execSync)("whoami",{encoding:"utf-8"}).trim();(0,F.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 $o(){let e=So.default.platform();if(e==="darwin")return yo();if(e==="linux")return bo();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var St=i(require("fs")),vo=i(require("os")),Io=i(require("path")),oe=require("child_process"),U=i(require("chalk"));var Co=Io.default.join(vo.default.homedir(),".openclaw","openclaw.json");function Bn(e=!1){let t=null;try{St.default.existsSync(Co)&&(t=JSON.parse(St.default.readFileSync(Co,"utf-8"))?.gateway?.mode??null)}catch{}if(typeof t=="string"&&t.length>0)return!0;e||console.log(U.default.dim(" Setting gateway.mode=local..."));try{return ee(()=>((0,oe.execSync)("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),!0))}catch(o){return e||(console.log(U.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${o.message}`)),console.log(U.default.yellow(" Run `openclaw config set gateway.mode local` manually."))),!1}}function qe(e={}){let t=e.verbose!==!1,o=a=>{t&&console.log(a)};o(U.default.dim(" Installing OpenClaw gateway service (if not present)...")),(0,oe.spawnSync)("openclaw",["gateway","install"],{stdio:t?"inherit":"pipe",shell:!0}).status!==0&&o(U.default.yellow(" \u26A0\uFE0F `openclaw gateway install` returned non-zero \u2014 continuing.")),Bn(!t),o(U.default.dim(" Starting OpenClaw gateway..."));let n=(0,oe.spawnSync)("openclaw",["gateway","start"],{stdio:t?"inherit":"pipe",shell:!0}),r="started";return n.status!==0&&(n=(0,oe.spawnSync)("openclaw",["gateway","restart"],{stdio:t?"inherit":"pipe",shell:!0}),r="restarted"),n.status!==0?{ok:!1,error:"gateway start/restart returned non-zero exit"}:{ok:!0,state:r}}function He(){if(process.platform!=="linux"||process.getuid?.()!==0)return;let e=(0,oe.spawnSync)("loginctl",["show-user","root","--property=Linger"],{encoding:"utf-8"});e.status===0&&/Linger=no/.test(e.stdout||"")&&(console.log(U.default.yellow(`
99
+ \u26A0\uFE0F systemd lingering is OFF for root. The gateway will stop on SSH disconnect.`)),console.log(U.default.dim(" Enable persistence: loginctl enable-linger root")))}var Fn=2e3,Un=12e4,Ro=new ko.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=Ht(),t=Jt(e),o=`${Xt}/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,Ao.default)(o);let s=(0,xo.default)("Waiting for authentication...").start(),n=no(),r=Date.now();for(;Date.now()-r<Un;){try{let a=await n.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:m,refresh_token:d,email:f}=a.data,I=mt(),B=`openclaw-${$t.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${I}`,q=B;try{let{version:A}=ne(),ce=await n.post("/api/v1/openclaw/register",{instance_id:B,label:$t.default.hostname(),version:A,machine_fingerprint:I},{headers:{Authorization:`Bearer ${c}`}}),M=ce.data?.result||ce.data;M&&typeof M.instance_id=="string"&&M.instance_id.length>0&&(q=M.instance_id)}catch(A){let ce=A?.response?.status;if(ce===403||ce===409){let M=A?.response?.data,hn=Array.isArray(M?.errors)&&typeof M.errors[0]=="string"?M.errors[0]:null,ct=M?.detail,wn=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,yn=hn||wn||`Login refused (status ${ce}). Open the BadgerClaw app to check your subscription state.`;s.fail(z.default.red(yn)),process.exit(1)}}Ne({access_token:c,user_id:l,instance_id:q,expires_at:m,refresh_token:d,email:f}),s.succeed(z.default.green(`Logged in as ${je(l)}`)),qe({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 x=await $e(!0);x>0&&console.log(z.default.green(`\u2705 ${x} bot(s) automatically paired to OpenClaw.`)),$o(),He();return}}catch{}await new Promise(a=>setTimeout(a,Fn))}s.fail(z.default.red("Authentication timed out. Please try again.")),process.exit(1)});var Eo=require("commander"),ke=i(require("chalk")),Je=i(require("fs")),de=i(require("os")),Ae=i(require("path")),xe=require("child_process");function Gn(){let e=process.platform;if(e==="darwin"){let t=Ae.default.join(de.default.homedir(),"Library","LaunchAgents","ai.badgerclaw.watch.plist");(0,xe.spawnSync)("launchctl",["unload",t],{stdio:"ignore"});try{Je.default.unlinkSync(t)}catch{}}else if(e==="linux"){(0,xe.spawnSync)("systemctl",["--user","disable","--now","badgerclaw-watch.service"],{stdio:"ignore"});let t=Ae.default.join(de.default.homedir(),".config","systemd","user","badgerclaw-watch.service");try{Je.default.unlinkSync(t)}catch{}(0,xe.spawnSync)("systemctl",["--user","daemon-reload"],{stdio:"ignore"})}(0,xe.spawnSync)("pkill",["-f","badgerclaw heartbeat"],{stdio:"ignore"})}function Po(e){try{return Je.default.rmSync(e,{recursive:!0,force:!0}),!0}catch{return!1}}var Oo=new Eo.Command("logout").description("Disconnect this machine, log out of BadgerClaw, and wipe local state").option("--keep-state","Only clear auth.json (legacy behaviour); preserve bot-mapping, claude-sessions, heartbeat logs, and plugin quarantine ledger").action(async e=>{let t=_();if(t)try{let a=Fe(t.access_token),{version:c}=ne();await a.post("/api/v1/openclaw/register",{instance_id:t.instance_id,label:de.default.hostname(),version:c,online:!1})}catch{}if(Gn(),e.keepState){we(),console.log(ke.default.green("Logged out \u2014 auth cleared. (state preserved with --keep-state)"));return}let o=Ae.default.join(de.default.homedir(),".badgerclaw"),s=Po(o),n=Ae.default.join(de.default.homedir(),".openclaw","badgerclaw"),r=Po(n);s||r?(console.log(ke.default.green("Logged out \u2014 local state cleared.")),console.log(ke.default.dim(` Removed: ${o}${r?`, ${n}`:""}`))):console.log(ke.default.green("Logged out."))});var Do=require("commander"),Ct=i(require("chalk"));var No=new Do.Command("status").description("Show connected instance info").action(async()=>{let e=_();(!e||!Te())&&(console.log(Ct.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(Ct.default.green("Authenticated")),console.log(` User: ${je(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var me=require("commander"),y=i(require("chalk")),Qe=i(require("ora")),Ye=i(require("fs")),Bo=i(require("os")),Mo=i(require("path")),Fo=require("child_process");var ue=i(require("fs")),To=i(require("os")),jo=i(require("path")),Lo=require("child_process");function ze(e){let t=e.split(":")[0].replace(/^@/,"").replace(/_bot$/,""),o=jo.join(To.homedir(),".openclaw","openclaw.json");return ue.existsSync(o)?{changed:ee(()=>{let n=JSON.parse(ue.readFileSync(o,"utf-8")),r=!1;if(n.channels?.badgerclaw?.accounts?.[t]&&(delete n.channels.badgerclaw.accounts[t],r=!0),n.agents?.list){let a=n.agents.list.length;n.agents.list=n.agents.list.filter(c=>c.id!==t),n.agents.list.length!==a&&(r=!0)}return r&&ue.writeFileSync(o,JSON.stringify(n,null,2)),r})}:{changed:!1}}function Ke(){try{return(0,Lo.execSync)("openclaw gateway restart",{stdio:"ignore"}),!0}catch{return!1}}function vt(){Te()||(console.log(y.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function Wn(e){return/^[a-z0-9_]{4,20}$/.test(e)}function Uo(e){return e.replace(/_bot$/,"")}var Vn=new me.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").action(async e=>{vt(),Wn(e)||(console.log(y.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let t=(0,Qe.default)(`Creating bot "${e}"...`).start();try{await k().post("/api/v1/openclaw/bots",{username:e}),t.succeed(y.default.green(`Bot "${e}" created successfully!`))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(y.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),qn=new me.Command("list").description("List your bots").action(async()=>{vt();let e=(0,Qe.default)("Fetching bots...").start();try{let s=(await k().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),s.length===0){console.log(y.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(y.default.green(`Your bots (${s.length}):
100
+ `));for(let n of s){let r=Uo(n.username||n.name),a=n.active===!1?y.default.dim("deactivated"):n.openclaw_connected?y.default.green("connected"):y.default.gray("disconnected");console.log(` ${y.default.bold(r)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(y.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),Hn=new me.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{vt();let t=(0,Qe.default)(`Deactivating bot "${e}"...`).start();try{await k().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(y.default.green(`Bot "${e}" deactivated.`));let{changed:s}=ze(e);s&&(console.log(y.default.dim(" Removed from openclaw.json")),Ke()&&console.log(y.default.dim(" Gateway restarted")))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(y.default.red(`Failed to deactivate bot: ${s}`)),process.exit(1)}});function Jn(e){let t=e.trim();return t.startsWith("@")&&(t=t.slice(1)),t.includes(":")&&(t=t.split(":")[0]),Uo(t)}function zn(e){let t=e.replace(/[^a-zA-Z0-9_.-]/g,"_")||"default";return Mo.default.join(Bo.default.homedir(),".openclaw","badgerclaw","quarantine",`${t}.json`)}var Kn=new me.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=Jn(e);t||(console.log(y.default.red(`Couldn't parse bot name "${e}".`)),process.exit(1));let o=zn(t),s=!1;if(Ye.default.existsSync(o))try{let n=JSON.parse(Ye.default.readFileSync(o,"utf-8")),r=n.failureCount??"?",a=n.quarantinedAt??"?";console.log(y.default.dim(` Quarantine for "${t}" \u2014 ${r} failures, since ${a}`)),Ye.default.unlinkSync(o),s=!0}catch(n){console.log(y.default.red(`Failed to clear quarantine ledger at ${o}: ${n.message}`)),process.exit(1)}console.log(s?y.default.green(`\u2705 Cleared quarantine for "${t}"`):y.default.dim(` No quarantine file for "${t}" \u2014 already healthy or never quarantined.`)),console.log(y.default.dim(" Restarting OpenClaw gateway so the refresh chain runs..."));try{(0,Fo.execSync)("openclaw gateway restart",{stdio:"inherit"})}catch(n){console.log(y.default.yellow(` Gateway restart command failed: ${n.message}`)),console.log(y.default.yellow(" Run `openclaw gateway restart` manually.")),process.exit(1)}console.log(y.default.green(`
101
+ \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(y.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(y.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(y.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(y.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),Go=new me.Command("bot").description("Manage bots").addCommand(Vn).addCommand(qn).addCommand(Hn).addCommand(Kn);var tn=require("commander"),h=i(require("chalk"));var Xe=i(require("axios")),Yn=7331,Wo=`http://localhost:${Yn}`,Qn=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,Xn=`http://127.0.0.1:${Qn}`,It="unknown";async function Zn(){try{return await Xe.default.get(Xn,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function Re(){try{let t=(await Xe.default.get(`${Wo}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(It=t.pluginVersion),t}catch{return{status:await Zn()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:It,bots:[]}}}function kt(e){e&&e!=="unknown"&&(It=e)}async function ge(){try{return{success:!0,message:(await Xe.default.post(`${Wo}/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 Ko=require("commander"),u=i(require("chalk")),Yo=i(require("axios"));var v=require("child_process"),p=i(require("fs")),b=i(require("path")),re=i(require("os")),P=i(require("axios"));async function W(e){return e.command_type==="update_cli"?rs(e.payload?.target_version):e.command_type==="update_plugin"?as(e.payload?.target_version):e.command_type==="restart_gateway"?ss():e.command_type==="leave_room"?bs(e.payload):e.command_type==="start_claude_code"?us(e.payload):e.command_type==="stop_claude_code"?ms(e.payload):e.command_type==="start_claude_control"?gs(e.payload):e.command_type==="stop_claude_control"?ps(e.payload):e.command_type==="update_claude_tools"?fs(e.payload):e.command_type==="bot_share_notify"?hs(e.payload):e.command_type==="bot_share_revoked"?ws(e.payload):e.command_type==="bot_share_expired"?ys(e.payload):e.command_type==="bot_refresh"?_s(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function ss(){try{return(0,v.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,v.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 rs(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,v.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,v.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),n=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return cs(),{success:!0,message:`Updated CLI to ${n}`,newVersion:n}}catch(o){let s=o.stderr?.toString()||o.message||"Unknown error";return s.includes("EACCES")||s.includes("permission")?{success:!1,message:"Permission denied. Run: sudo npm install -g badgerclaw"}:{success:!1,message:`CLI update failed: ${s.slice(0,500)}`}}}async function as(e){let t=b.default.join(re.default.homedir(),".openclaw","extensions","badgerclaw"),o=b.default.join(re.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),s=p.default.existsSync(o)?"npm":p.default.existsSync(t)?"legacy":null;if(s===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 n=e?`@badgerclaw/connect@${e}`:"@badgerclaw/connect@latest";try{if(s==="npm"){let d=b.default.dirname(b.default.dirname(b.default.dirname(o)));(0,v.execSync)(`npm install ${n}`,{cwd:d,stdio:"pipe",timeout:12e4});let f=b.default.join(o,"package.json"),I="unknown";p.default.existsSync(f)&&(I=JSON.parse(p.default.readFileSync(f,"utf-8")).version||"unknown"),kt(I);try{(0,v.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await qo(I)}let r=t;(0,v.execSync)(`npm install ${n}`,{cwd:r,stdio:"pipe",timeout:12e4});let a=b.default.join(r,"node_modules","@badgerclaw","connect"),c=b.default.join(a,"package.json"),l="unknown";p.default.existsSync(c)&&(l=JSON.parse(p.default.readFileSync(c,"utf-8")).version||"unknown"),kt(l),is(a,r);let m=b.default.join(r,"package.json");if(p.default.existsSync(m)&&p.default.existsSync(c))try{let d=JSON.parse(p.default.readFileSync(m,"utf-8")),f=JSON.parse(p.default.readFileSync(c,"utf-8"));d.version=l,f.openclaw&&(d.openclaw={...d.openclaw,...f.openclaw}),p.default.writeFileSync(m,JSON.stringify(d,null,2)+`
102
+ `)}catch{}try{(0,v.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await qo(l)}catch(r){return{success:!1,message:`Plugin update failed: ${(r.stderr?.toString()||r.message||"").slice(0,500)}`}}}async function qo(e){for(let t=0;t<15;t++){await new Promise(o=>setTimeout(o,1e3));try{let o=await P.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 is(e,t){let o=b.default.join(e,"dist"),s=b.default.join(t,"dist");p.default.existsSync(o)&&(p.default.mkdirSync(s,{recursive:!0}),Bt(o,s));let n=b.default.join(e,"openclaw.plugin.json");p.default.existsSync(n)&&p.default.copyFileSync(n,b.default.join(t,"openclaw.plugin.json"));let r=b.default.join(e,"scripts"),a=b.default.join(t,"scripts");p.default.existsSync(r)&&(p.default.mkdirSync(a,{recursive:!0}),Bt(r,a));for(let c of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let l=b.default.join(t,c);p.default.existsSync(l)&&(p.default.statSync(l).isDirectory()?p.default.rmSync(l,{recursive:!0,force:!0}):p.default.unlinkSync(l))}}function Bt(e,t){for(let o of p.default.readdirSync(e,{withFileTypes:!0})){let s=b.default.join(e,o.name),n=b.default.join(t,o.name);o.isDirectory()?(p.default.mkdirSync(n,{recursive:!0}),Bt(s,n)):p.default.copyFileSync(s,n)}}function cs(){try{try{(0,v.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,v.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,v.execSync)("sleep 1",{stdio:"pipe"});let e=(0,v.execSync)("which badgerclaw",{stdio:"pipe"}).toString().trim();(0,v.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,v.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function ls(){let e=b.default.join(re.default.homedir(),".badgerclaw","workspace");p.default.mkdirSync(e,{recursive:!0});let t=b.default.join(e,".git");return p.default.existsSync(t)||(0,v.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),p.default.writeFileSync(b.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
103
103
 
104
104
  When you receive a message, it will be formatted like:
105
105
  [Room: RoomName] Sender: message text
@@ -108,24 +108,26 @@ Reply using the reply tool with botId="..." and roomId="..."
108
108
  ALWAYS use the \`reply\` MCP tool to send your response back to the chat room.
109
109
  Use the exact botId and roomId provided in the message \u2014 do not modify them.
110
110
  Keep responses concise and helpful.
111
- `),e}var Ze=b.default.join(ue.default.homedir(),".badgerclaw","claude-code.lock");function is(){try{m.default.mkdirSync(b.default.dirname(Ze),{recursive:!0});try{let e=m.default.statSync(Ze);if(Date.now()-e.mtimeMs<6e4)return!1;m.default.unlinkSync(Ze)}catch{}return m.default.writeFileSync(Ze,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function cs(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!is())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 ke(e.bot_id),{launchClaudeCode:o,recordSession:s,getActiveSessions:n,stopSession:r}=(Xe(),Ft(Dt)),a=new Set;try{let se=(await R.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let G of se)if(G.botId!==t&&G.enabled!==!1){let V=G.port;typeof V=="number"&&V>=7332&&a.add(V)}}catch{}for(let S=7332;S<=7340;S++)try{(0,C.execSync)(`lsof -ti :${S} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(S)}catch{}let i=7332;for(;a.has(i);)i++;let l=n();for(let S of l)S.port===i&&(console.log(`[command-executor] Stopping existing session ${S.sessionId} on port ${i}`),r(S.sessionId));try{(0,C.execSync)(`lsof -ti :${i} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let y=e.session_id||`session-${Date.now()}`;await R.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:y,port:i},{timeout:1e4});let _=as();return o({sessionId:y,port:i,projectDir:_}),s(y,0,0,i,_),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${y}, port: ${i})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function ke(e){if(e.startsWith("@"))return e;try{let o=(await R.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],s=b.default.join(ue.default.homedir(),".badgerclaw","bot-mapping.json");if(m.default.existsSync(s)){let n=JSON.parse(m.default.readFileSync(s,"utf-8"));if(n[e])return n[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 ls(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 ke(e.bot_id),o=e.session_id;if(!o)try{let s=await R.default.get("http://localhost:7331/claude-code/status",{timeout:5e3}),r=(s.data?.bots||s.data?.rooms||[]).find(a=>a.botId===t);r&&(o=r.sessionId)}catch{}if(await R.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:s}=(Xe(),Ft(Dt));s(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 ds(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 ke(t));let s=e?.session_id||`cc-${Date.now()}`;return await R.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!0,sessionId:s,mode:"primary",tools:e?.tools},{timeout:1e4}),console.log(`[claude-control] Primary mode enabled for ${o} (session: ${s})`),{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 us(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 ke(t)),await R.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 ms(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 ke(t)),await R.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 gs(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 R.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 R.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 fs(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 R.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 hs(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 s=b.default.join(ue.default.homedir(),".openclaw","badgerclaw","quarantine",`${o}.json`);try{m.default.rmSync(s,{force:!0})}catch{}try{return(0,C.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 ws(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 R.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 Go=3e4,ys=15e4,Jo="/api/v1/dashboard/heartbeat",_s="/api/v1/dashboard/disconnect",bs="/api/v1/me/active-shares",Ss=3e3,Vo=!1,et=new Map,$s=3e4;function tt(e,t){if(e!=="start_claude_code"&&e!=="stop_claude_code")return!1;let o=`${e}:${t||"unknown"}`,s=Date.now();for(let[n,r]of et)s-r>$s&&et.delete(n);return et.has(o)?!0:(et.set(o,s),!1)}function zo(e,t){let o=Te();return{instance_id:N(),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,bots:e.bots.map(s=>({bot_id:s.botId,bot_username:s.botUsername,status:s.status,activity_state:s.activityState||"idle",active_task:s.activeTask||null,last_activity_at:s.lastActivity,messages_received:s.messagesReceived,messages_sent:s.messagesSent,chunked_messages:s.chunkedMessages,total_chunks_sent:s.totalChunksSent,errors:s.errors,last_error:s.lastError,last_error_at:s.lastErrorAt,uptime_seconds:s.uptimeSeconds,rooms_active:s.roomsActive,room_details:(s.roomDetails||[]).map(n=>({roomId:n.roomId,roomName:n.roomName,workspaceName:n.workspaceName||null,messagesInRoom:n.messagesInRoom,lastActivityInRoom:n.lastActivityInRoom})),claude_code_enabled:s.claudeCodeEnabled??!1,claude_code_session_id:s.claudeCodeSessionId??null,quarantined:s.quarantined??!1}))}}async function P(){let{version:e}=ee(),t=await xe(),o=zo(t,e);await I().post(Jo,o)}function Cs(e,t){if(!e||e.status!==t.status)return!0;let o=new Map(e.bots.map(s=>[s.botId,s]));for(let s of t.bots){let n=o.get(s.botId);if(!n||n.status!==s.status||n.errors!==s.errors)return!0}return e.bots.length!==t.bots.length}async function Wo(){try{let o=(await I().get(bs)).data?.shares||[],s={shares:o.map(n=>({botUserId:n.bot_user_id,sharedWithUserId:n.shared_with_user_id,expiresAt:n.expires_at||null,shareId:n.share_id}))};await Ho.default.post("http://localhost:7331/bot-share/sync",s,{timeout:1e4}),console.log(d.default.dim(` [${w()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(d.default.dim(` [${w()}] Share sync failed (non-fatal): ${e.message}`))}}async function vs(){if(!Vo){Vo=!0;try{await I().post(_s,{instance_id:N()},{timeout:Ss}),console.log(d.default.dim(` [${new Date().toISOString()}] Posted disconnect \u2014 dashboard will mark machine offline immediately.`))}catch(e){console.log(d.default.dim(` [${new Date().toISOString()}] Disconnect post failed (non-fatal): ${e?.message||e}`))}}}var Yo=new qo.Command("heartbeat").description("Run heartbeat daemon \u2014 reports telemetry to the BadgerClaw dashboard every 30s").action(async()=>{let e=h();e||(console.log(d.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=ee();console.log(d.default.green(`Heartbeat daemon started (v${t})`)),console.log(d.default.dim(` Instance: ${N()}`)),console.log(d.default.dim(` Interval: ${Go/1e3}s`)),console.log(d.default.dim(` Press Ctrl+C to stop.
112
- `));let o=null,s=10,n=0,r=async()=>{try{await Ko();let i=await xe(),l=zo(i,t);Cs(o,i)&&o!==null&&console.log(d.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let _=I(),S=await _.post(Jo,l);n=0;let se=i.bots.length,G=i.bots.filter(x=>x.status==="running").length;console.log(d.default.dim(` [${new Date().toISOString()}] gateway=${i.status} bots=${G}/${se} running mem=${l.mem_free_mb}MB free`)),o=i;let V=S.data?.pending_commands||[],st=!1;for(let x of V)try{if(console.log(d.default.cyan(` [${new Date().toISOString()}] Received command: ${x.command_type} (${x.id})`)),await _.post(`/api/v1/dashboard/commands/${x.id}/ack`),tt(x.command_type,x.payload?.bot_id)){console.log(d.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${x.command_type}`));continue}let k=await F(x);console.log(k.success?d.default.green(` [${new Date().toISOString()}] ${k.message}`):d.default.red(` [${new Date().toISOString()}] ${k.message}`)),await _.post(`/api/v1/dashboard/commands/${x.id}/result`,{status:k.success?"success":"failed",result:k.message,new_version:k.newVersion||null}),x.command_type==="update_cli"&&k.success&&(st=!0)}catch(k){console.log(d.default.dim(` [${new Date().toISOString()}] Command ${x.id} error: ${k.message}`))}if(st){console.log(d.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await P()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(i){i instanceof ae&&(console.log(d.default.yellow(` [${new Date().toISOString()}] Account deactivated \u2014 signed out. Exiting daemon.`)),process.exit(0)),n+=1,console.log(d.default.dim(` [${new Date().toISOString()}] Heartbeat failed (${n}/${s}): ${i.message}`)),n>=s&&(console.log(d.default.red(` [${new Date().toISOString()}] ${s} consecutive heartbeat failures \u2014 exiting so launchctl/systemd can restart the daemon.`)),process.exit(1))}};await r(),await Wo(),setInterval(r,Go),setInterval(Wo,ys),xs(e.access_token,t);let a=i=>{console.log(d.default.yellow(`
113
- [${new Date().toISOString()}] Received ${i} \u2014 posting disconnect and exiting.`)),vs().finally(()=>{process.exit(0)})};process.on("SIGTERM",a),process.on("SIGINT",a),await new Promise(()=>{})});async function Ko(){let e=h();if(!e?.expires_at)return;let t=new Date(e.expires_at).getTime(),o=Date.now(),s=300*1e3;if(t-o<s)if(console.log(d.default.dim(` [${w()}] Token expires soon \u2014 refreshing proactively...`)),await dt())console.log(d.default.green(` [${w()}] Token refreshed successfully`));else{let r=Kt()||"unknown reason";console.log(d.default.yellow(` [${w()}] Token refresh failed: ${r}`))}}var Is=2700*1e3;function xs(e,t){let o=3e3,s=3e4,n=null;async function r(){try{await Ko();let i=h()?.access_token||e,l=require("eventsource"),y=new l(`${E}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${i}`}});y.onopen=()=>{o=3e3,console.log(d.default.dim(` [${w()}] SSE connected \u2014 listening for real-time events`)),n&&clearTimeout(n),n=setTimeout(()=>{console.log(d.default.dim(` [${w()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),y.close(),r()},Is)},y.onmessage=async _=>{try{let S=JSON.parse(_.data);await ks(S)}catch{}},y.onerror=async()=>{y.close(),n&&(clearTimeout(n),n=null),console.log(d.default.dim(` [${w()}] SSE disconnected \u2014 reconnecting in ${o/1e3}s...`)),setTimeout(r,o),o=Math.min(o*1.5,s)}}catch(a){console.log(d.default.dim(` [${w()}] SSE connection failed: ${a.message}`)),setTimeout(r,o),o=Math.min(o*1.5,s)}}r()}function w(){return new Date().toISOString()}async function ks(e){if(e.type==="pair"){console.log(d.default.cyan(` [${w()}] Pair event: ${e.bot_name}`)),await ye(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(d.default.green(` [${w()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await P()}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(d.default.yellow(` [${w()}] Bot deleted: ${t}`));try{let s=await import("fs"),n=await import("path"),r=await import("os"),a=n.join(r.homedir(),".openclaw","openclaw.json");if(Q(()=>{let l=JSON.parse(s.readFileSync(a,"utf-8")),y=!1;if(l.channels?.badgerclaw?.accounts?.[o]&&(delete l.channels.badgerclaw.accounts[o],y=!0),l.agents?.list){let _=l.agents.list.length;l.agents.list=l.agents.list.filter(S=>S.id!==o),l.agents.list.length!==_&&(y=!0)}return y&&s.writeFileSync(a,JSON.stringify(l,null,2)),y})){console.log(d.default.green(` [${w()}] Removed "${o}" from openclaw.json`));let{execSync:l}=await import("child_process");try{l("openclaw gateway restart",{stdio:"ignore"}),console.log(d.default.green(` [${w()}] Gateway restarted`))}catch{}}}catch(s){console.log(d.default.red(` [${w()}] Failed to clean up bot: ${s}`))}try{await P()}catch{}}else if(e.type==="gateway-restart"){console.log(d.default.cyan(` [${w()}] Remote gateway-restart received`));let t=await de();console.log(t.success?d.default.green(` [${w()}] Gateway restarted`):d.default.red(` [${w()}] Gateway restart failed: ${t.message}`));try{await P()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(d.default.cyan(` [${w()}] Claude Code START: bot=${e.bot_id}`)),tt("start_claude_code",e.bot_id)){console.log(d.default.dim(` [${w()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await F({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 I().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await P()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(d.default.cyan(` [${w()}] Claude Code STOP: bot=${e.bot_id}`)),tt("stop_claude_code",e.bot_id)){console.log(d.default.dim(` [${w()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await F({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 I().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await P()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(d.default.cyan(` [${w()}] Command: ${e.command_type} (${e.command_id})`)),tt(e.command_type,e.payload?.bot_id)){console.log(d.default.dim(` [${w()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=I();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await F({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(d.default.cyan(` [${w()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await P()}catch{}}}var Xo=new Qo.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{let e=h();e||(console.log(g.default.yellow("Not logged in.")),process.exit(1)),await _e(!1),console.log(g.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=new t(`${E}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${e.access_token}`}});o.onmessage=async s=>{try{let n=JSON.parse(s.data);if(n.type==="pair"){let r=n.target_instance_id;if(r&&r!==N()){console.log(g.default.dim(`
114
- \u{1F4F1} Pair event for ${n.bot_name} targets ${r} \u2014 not us, skipping`));return}console.log(g.default.cyan(`
115
- \u{1F4F1} Pair event received: ${n.bot_name}`)),await ye(n.pair_code,n.bot_name,n.bot_user_id,!1);try{let{execSync:a}=await import("child_process");a("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(" \u2705 Gateway restarted \u2014 bot is live!"))}catch{console.log(g.default.dim(" Gateway restart failed \u2014 run: openclaw gateway restart"))}}else if(n.type==="gateway-restart"){console.log(g.default.cyan(`
116
- \u{1F504} Remote gateway-restart command received`));let r=await de();r.success?console.log(g.default.green(` \u2705 Gateway restarted: ${r.message}`)):console.log(g.default.red(` \u274C Gateway restart failed: ${r.message}`));try{await P(),console.log(g.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(g.default.dim(" Could not push heartbeat."))}}else if((n.type==="bot.delete"||n.type==="bot.disconnect")&&n.bot_user_id){let r=n.bot_user_id,a=n.type==="bot.delete"?"deleted":"disconnected",i=n.type==="bot.delete"?"\u{1F5D1}\uFE0F ":"\u{1F50C}";console.log(g.default.yellow(`
117
- ${i} Bot ${a}: ${r} \u2014 removing from OpenClaw config...`));try{let{changed:l}=qe(r);l?(console.log(g.default.green(" \u2705 Removed from openclaw.json")),He()?console.log(g.default.green(" \u2705 Gateway restarted")):console.log(g.default.dim(" Gateway restart failed \u2014 restart manually"))):console.log(g.default.dim(" Account not found in openclaw.json \u2014 nothing to remove"))}catch(l){console.log(g.default.red(` Failed to update openclaw.json: ${l}`))}}else if(n.type==="claude_code.start"&&n.bot_id&&n.room_id){console.log(g.default.cyan(`
118
- \u{1F916} Claude Code START received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await F({id:n.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:n.bot_id,room_id:n.room_id,session_id:n.session_id}});if(console.log(r.success?g.default.green(` \u2705 ${r.message}`):g.default.red(` \u274C ${r.message}`)),n.command_id)try{await I().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await P()}catch{}}catch(r){console.log(g.default.red(` Claude Code start error: ${r.message}`))}}else if(n.type==="claude_code.stop"&&n.bot_id&&n.room_id){console.log(g.default.cyan(`
119
- \u{1F916} Claude Code STOP received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await F({id:n.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:n.bot_id,room_id:n.room_id,session_id:n.session_id}});if(console.log(r.success?g.default.green(` \u2705 ${r.message}`):g.default.red(` \u274C ${r.message}`)),n.command_id)try{await I().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await P()}catch{}}catch(r){console.log(g.default.red(` Claude Code stop error: ${r.message}`))}}else if(n.type==="command.execute"&&n.command_id){console.log(g.default.cyan(`
120
- \u26A1 SSE command received: ${n.command_type} (${n.command_id})`));try{let r=I();await r.post(`/api/v1/dashboard/commands/${n.command_id}/ack`);let a=await F({id:n.command_id,command_type:n.command_type,payload:n.payload});console.log(a.success?g.default.green(` \u2705 ${a.message}`):g.default.red(` \u274C ${a.message}`)),await r.post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:a.success?"success":"failed",result:a.message,new_version:a.newVersion||null});try{await P()}catch{}n.command_type==="update_cli"&&a.success&&(console.log(g.default.cyan(" CLI updated \u2014 restarting in 2s...")),setTimeout(()=>process.exit(0),2e3))}catch(r){console.log(g.default.red(` Command ${n.command_id} error: ${r.message}`))}}}catch{}},o.onerror=()=>{console.log(g.default.dim(" Reconnecting..."))},await new Promise(()=>{})});var nn=require("commander"),u=c(require("chalk")),Ae=require("child_process"),v=c(require("fs")),Lt=c(require("os")),Bt=c(require("path"));var en=c(require("fs")),tn=c(require("os")),ot=c(require("path")),Nt=require("child_process"),J=c(require("chalk"));var As=`${E}/api/v1/dashboard/versions/latest`,Rs=2500,Ps=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),Zo=ot.default.join(tn.default.homedir(),".openclaw/extensions/badgerclaw"),Es=[ot.default.join(Zo,"node_modules/@badgerclaw/connect/package.json"),ot.default.join(Zo,"package.json")];function jt(){return"0.2.48"}function Os(){for(let e of Es)try{let t=en.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 Ds(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function nt(){if((0,Nt.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,Nt.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:Ds(t.stdout)||null}async function Ts(){let e=new AbortController,t=setTimeout(()=>e.abort(),Rs);try{let o=await fetch(As,{signal:e.signal});if(!o.ok)return null;let s=await o.json(),n=s.result&&typeof s.result=="object"?s.result:s;return{cli:n.cli??"unknown",plugin:n.plugin??"unknown",supported_openclaw:n.supported_openclaw??"unknown"}}catch{return null}finally{clearTimeout(t)}}function Ns(e){let t=[];if(e.cli&&e.cli!=="unknown"){let o=jt();o!==e.cli&&t.push({component:"cli",current:o,approved:e.cli})}if(e.plugin&&e.plugin!=="unknown"){let o=Os();(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=nt();(o===null||o!==e.supported_openclaw)&&t.push({component:"openclaw",current:o??"not installed",approved:e.supported_openclaw})}return t}function js(e){return e[2]}function Ls(e){return!e||e.startsWith("-")?!0:Ps.has(e)}function Bs(e){let t=[];t.push(""),t.push(J.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let s=o.component.padEnd(8);t.push(` ${s} ${J.default.yellow(o.current)} \u2192 ${J.default.green(o.approved)} ${J.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(J.default.green(" To fix, run:")),t.push(J.default.green.bold(" badgerclaw setup")),t.push(""),t.push(J.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
121
- `)}async function on(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=js(e);if(Ls(t))return;let o=await Ts();if(!o)return;let s=Ns(o);s.length!==0&&(process.stderr.write(Bs(s)),process.exit(1))}var D=Bt.default.join(Lt.default.homedir(),".openclaw","openclaw.json"),Re=D+".badgerclaw-stash";async function Ms(){try{let e=await fetch(`${E}/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,s=n=>typeof n!="string"||!n||n==="unknown"?null:n;return{cli:s(o.cli),plugin:s(o.plugin),openclaw:s(o.supported_openclaw)}}catch{return{cli:null,plugin:null,openclaw:null}}}function Us(){if(!v.default.existsSync(D))return null;try{let e=JSON.parse(v.default.readFileSync(D,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,v.default.writeFileSync(D,JSON.stringify(e,null,2)),v.default.writeFileSync(Re,JSON.stringify(t,null,2)),t):null}catch{return null}}function Fs(){if(!v.default.existsSync(D))return null;try{let e=JSON.parse(v.default.readFileSync(D,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function Gs(e){if(e&&v.default.existsSync(D))try{let t=JSON.parse(v.default.readFileSync(D,"utf-8"));t.gateway={...e,...t.gateway||{}},v.default.writeFileSync(D,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 Vs(){if(v.default.existsSync(Re))try{let e=JSON.parse(v.default.readFileSync(Re,"utf-8")),t=JSON.parse(v.default.readFileSync(D,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,v.default.writeFileSync(D,JSON.stringify(t,null,2)),v.default.unlinkSync(Re)}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: ${Re}`))}}var sn=new nn.Command("setup").description("Install or update the OpenClaw BadgerClaw plugin safely (handles config automatically)").action(async()=>{console.log(u.default.green(`
111
+ `),e}var ot=b.default.join(re.default.homedir(),".badgerclaw","claude-code.lock");function ds(){try{p.default.mkdirSync(b.default.dirname(ot),{recursive:!0});try{let e=p.default.statSync(ot);if(Date.now()-e.mtimeMs<6e4)return!1;p.default.unlinkSync(ot)}catch{}return p.default.writeFileSync(ot,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function us(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!ds())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 Pe(e.bot_id),{launchClaudeCode:o,recordSession:s,getActiveSessions:n,stopSession:r}=(tt(),qt(Lt)),a=new Set;try{let I=(await P.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let B of I)if(B.botId!==t&&B.enabled!==!1){let q=B.port;typeof q=="number"&&q>=7332&&a.add(q)}}catch{}for(let f=7332;f<=7340;f++)try{(0,v.execSync)(`lsof -ti :${f} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(f)}catch{}let c=7332;for(;a.has(c);)c++;let l=n();for(let f of l)f.port===c&&(console.log(`[command-executor] Stopping existing session ${f.sessionId} on port ${c}`),r(f.sessionId));try{(0,v.execSync)(`lsof -ti :${c} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let m=e.session_id||`session-${Date.now()}`;await P.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:m,port:c},{timeout:1e4});let d=ls();return o({sessionId:m,port:c,projectDir:d}),s(m,0,0,c,d),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${m}, port: ${c})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Pe(e){if(e.startsWith("@"))return e;try{let o=(await P.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],s=b.default.join(re.default.homedir(),".badgerclaw","bot-mapping.json");if(p.default.existsSync(s)){let n=JSON.parse(p.default.readFileSync(s,"utf-8"));if(n[e])return n[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 ms(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 Pe(e.bot_id),o=e.session_id;if(!o)try{let s=await P.default.get("http://localhost:7331/claude-code/status",{timeout:5e3}),r=(s.data?.bots||s.data?.rooms||[]).find(a=>a.botId===t);r&&(o=r.sessionId)}catch{}if(await P.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:s}=(tt(),qt(Lt));s(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 gs(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 Pe(t));let s=e?.session_id||`cc-${Date.now()}`;return await P.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!0,sessionId:s,mode:"primary",tools:e?.tools},{timeout:1e4}),console.log(`[claude-control] Primary mode enabled for ${o} (session: ${s})`),{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 ps(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 Pe(t)),await P.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 fs(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 Pe(t)),await P.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 hs(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 P.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 ws(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 P.default.post("http://localhost:7331/bot-share/revoked",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,botDisplayName:e.bot_name||void 0},{timeout:1e4}),console.log(`[bot-share] Revoked: ${e.shared_with_user_id} lost access to ${e.bot_user_id}`),{success:!0,message:`Share revocation sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to revoke share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function ys(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await P.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 _s(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 s=b.default.join(re.default.homedir(),".openclaw","badgerclaw","quarantine",`${o}.json`);try{p.default.rmSync(s,{force:!0})}catch{}try{return(0,v.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 bs(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 P.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 Ho=3e4,Ss=15e4,Qo="/api/v1/dashboard/heartbeat",$s="/api/v1/dashboard/disconnect",Cs="/api/v1/me/active-shares",vs=3e3,Jo=!1,nt=new Map,Is=3e4;function st(e,t){if(e!=="start_claude_code"&&e!=="stop_claude_code")return!1;let o=`${e}:${t||"unknown"}`,s=Date.now();for(let[n,r]of nt)s-r>Is&&nt.delete(n);return nt.has(o)?!0:(nt.set(o,s),!1)}function Xo(e,t){let o=Le();return{instance_id:j(),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,bots:e.bots.map(s=>({bot_id:s.botId,bot_username:s.botUsername,status:s.status,activity_state:s.activityState||"idle",active_task:s.activeTask||null,last_activity_at:s.lastActivity,messages_received:s.messagesReceived,messages_sent:s.messagesSent,chunked_messages:s.chunkedMessages,total_chunks_sent:s.totalChunksSent,errors:s.errors,last_error:s.lastError,last_error_at:s.lastErrorAt,uptime_seconds:s.uptimeSeconds,rooms_active:s.roomsActive,room_details:(s.roomDetails||[]).map(n=>({roomId:n.roomId,roomName:n.roomName,workspaceName:n.workspaceName||null,messagesInRoom:n.messagesInRoom,lastActivityInRoom:n.lastActivityInRoom})),claude_code_enabled:s.claudeCodeEnabled??!1,claude_code_session_id:s.claudeCodeSessionId??null,quarantined:s.quarantined??!1}))}}async function E(){let{version:e}=ne(),t=await Re(),o=Xo(t,e);await k().post(Qo,o)}function ks(e,t){if(!e||e.status!==t.status)return!0;let o=new Map(e.bots.map(s=>[s.botId,s]));for(let s of t.bots){let n=o.get(s.botId);if(!n||n.status!==s.status||n.errors!==s.errors)return!0}return e.bots.length!==t.bots.length}async function zo(){try{let o=(await k().get(Cs)).data?.shares||[],s={shares:o.map(n=>({botUserId:n.bot_user_id,sharedWithUserId:n.shared_with_user_id,expiresAt:n.expires_at||null,shareId:n.share_id}))};await Yo.default.post("http://localhost:7331/bot-share/sync",s,{timeout:1e4}),console.log(u.default.dim(` [${S()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(u.default.dim(` [${S()}] Share sync failed (non-fatal): ${e.message}`))}}async function xs(){if(!Jo){Jo=!0;try{await k().post($s,{instance_id:j()},{timeout:vs}),console.log(u.default.dim(` [${new Date().toISOString()}] Posted disconnect \u2014 dashboard will mark machine offline immediately.`))}catch(e){console.log(u.default.dim(` [${new Date().toISOString()}] Disconnect post failed (non-fatal): ${e?.message||e}`))}}}var Zo=new Ko.Command("heartbeat").description("Run heartbeat daemon \u2014 reports telemetry to the BadgerClaw dashboard every 30s").action(async()=>{let e=_();e||(console.log(u.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=ne();console.log(u.default.green(`Heartbeat daemon started (v${t})`)),console.log(u.default.dim(` Instance: ${j()}`)),console.log(u.default.dim(` Interval: ${Ho/1e3}s`)),console.log(u.default.dim(` Press Ctrl+C to stop.
112
+ `));let o=null,s=10,n=0,r=async()=>{try{await en();let c=await Re(),l=Xo(c,t);ks(o,c)&&o!==null&&console.log(u.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let d=k(),f=await d.post(Qo,l);n=0;let I=c.bots.length,B=c.bots.filter(x=>x.status==="running").length;console.log(u.default.dim(` [${new Date().toISOString()}] gateway=${c.status} bots=${B}/${I} running mem=${l.mem_free_mb}MB free`)),o=c;let q=f.data?.pending_commands||[],it=!1;for(let x of q)try{if(console.log(u.default.cyan(` [${new Date().toISOString()}] Received command: ${x.command_type} (${x.id})`)),await d.post(`/api/v1/dashboard/commands/${x.id}/ack`),st(x.command_type,x.payload?.bot_id)){console.log(u.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${x.command_type}`));continue}let A=await W(x);console.log(A.success?u.default.green(` [${new Date().toISOString()}] ${A.message}`):u.default.red(` [${new Date().toISOString()}] ${A.message}`)),await d.post(`/api/v1/dashboard/commands/${x.id}/result`,{status:A.success?"success":"failed",result:A.message,new_version:A.newVersion||null}),x.command_type==="update_cli"&&A.success&&(it=!0)}catch(A){console.log(u.default.dim(` [${new Date().toISOString()}] Command ${x.id} error: ${A.message}`))}if(it){console.log(u.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await E()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(c){c instanceof le&&(console.log(u.default.yellow(` [${new Date().toISOString()}] Account deactivated \u2014 signed out. Exiting daemon.`)),process.exit(0)),n+=1,console.log(u.default.dim(` [${new Date().toISOString()}] Heartbeat failed (${n}/${s}): ${c.message}`)),n>=s&&(console.log(u.default.red(` [${new Date().toISOString()}] ${s} consecutive heartbeat failures \u2014 exiting so launchctl/systemd can restart the daemon.`)),process.exit(1))}};await r(),await zo(),setInterval(r,Ho),setInterval(zo,Ss),Rs(e.access_token,t);let a=c=>{console.log(u.default.yellow(`
113
+ [${new Date().toISOString()}] Received ${c} \u2014 posting disconnect and exiting.`)),xs().finally(()=>{process.exit(0)})};process.on("SIGTERM",a),process.on("SIGINT",a),await new Promise(()=>{})});async function en(){let e=_();if(!e?.expires_at)return;let t=new Date(e.expires_at).getTime(),o=Date.now(),s=300*1e3;if(t-o<s)if(console.log(u.default.dim(` [${S()}] Token expires soon \u2014 refreshing proactively...`)),await gt())console.log(u.default.green(` [${S()}] Token refreshed successfully`));else{let r=eo()||"unknown reason";console.log(u.default.yellow(` [${S()}] Token refresh failed: ${r}`))}}var As=2700*1e3;function Rs(e,t){let o=3e3,s=3e4,n=null;async function r(){try{await en();let c=_()?.access_token||e,l=require("eventsource"),m=new l(`${O}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${c}`}});m.onopen=()=>{o=3e3,console.log(u.default.dim(` [${S()}] SSE connected \u2014 listening for real-time events`)),n&&clearTimeout(n),n=setTimeout(()=>{console.log(u.default.dim(` [${S()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),m.close(),r()},As)},m.onmessage=async d=>{try{let f=JSON.parse(d.data);await Ps(f)}catch{}},m.onerror=async()=>{m.close(),n&&(clearTimeout(n),n=null),console.log(u.default.dim(` [${S()}] SSE disconnected \u2014 reconnecting in ${o/1e3}s...`)),setTimeout(r,o),o=Math.min(o*1.5,s)}}catch(a){console.log(u.default.dim(` [${S()}] SSE connection failed: ${a.message}`)),setTimeout(r,o),o=Math.min(o*1.5,s)}}r()}function S(){return new Date().toISOString()}async function Ps(e){if(e.type==="pair"){console.log(u.default.cyan(` [${S()}] Pair event: ${e.bot_name}`)),await Se(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(u.default.green(` [${S()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await E()}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(u.default.yellow(` [${S()}] Bot deleted: ${t}`));try{let s=await import("fs"),n=await import("path"),r=await import("os"),a=n.join(r.homedir(),".openclaw","openclaw.json");if(ee(()=>{let l=JSON.parse(s.readFileSync(a,"utf-8")),m=!1;if(l.channels?.badgerclaw?.accounts?.[o]&&(delete l.channels.badgerclaw.accounts[o],m=!0),l.agents?.list){let d=l.agents.list.length;l.agents.list=l.agents.list.filter(f=>f.id!==o),l.agents.list.length!==d&&(m=!0)}return m&&s.writeFileSync(a,JSON.stringify(l,null,2)),m})){console.log(u.default.green(` [${S()}] Removed "${o}" from openclaw.json`));let{execSync:l}=await import("child_process");try{l("openclaw gateway restart",{stdio:"ignore"}),console.log(u.default.green(` [${S()}] Gateway restarted`))}catch{}}}catch(s){console.log(u.default.red(` [${S()}] Failed to clean up bot: ${s}`))}try{await E()}catch{}}else if(e.type==="gateway-restart"){console.log(u.default.cyan(` [${S()}] Remote gateway-restart received`));let t=await ge();console.log(t.success?u.default.green(` [${S()}] Gateway restarted`):u.default.red(` [${S()}] Gateway restart failed: ${t.message}`));try{await E()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(u.default.cyan(` [${S()}] Claude Code START: bot=${e.bot_id}`)),st("start_claude_code",e.bot_id)){console.log(u.default.dim(` [${S()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await W({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 k().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await E()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(u.default.cyan(` [${S()}] Claude Code STOP: bot=${e.bot_id}`)),st("stop_claude_code",e.bot_id)){console.log(u.default.dim(` [${S()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await W({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 k().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await E()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(u.default.cyan(` [${S()}] Command: ${e.command_type} (${e.command_id})`)),st(e.command_type,e.payload?.bot_id)){console.log(u.default.dim(` [${S()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=k();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await W({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(u.default.cyan(` [${S()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await E()}catch{}}}var on=new tn.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{let e=_();e||(console.log(h.default.yellow("Not logged in.")),process.exit(1)),await $e(!1),console.log(h.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=new t(`${O}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${e.access_token}`}});o.onmessage=async s=>{try{let n=JSON.parse(s.data);if(n.type==="pair"){let r=n.target_instance_id;if(r&&r!==j()){console.log(h.default.dim(`
114
+ \u{1F4F1} Pair event for ${n.bot_name} targets ${r} \u2014 not us, skipping`));return}console.log(h.default.cyan(`
115
+ \u{1F4F1} Pair event received: ${n.bot_name}`)),await Se(n.pair_code,n.bot_name,n.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(n.type==="gateway-restart"){console.log(h.default.cyan(`
116
+ \u{1F504} Remote gateway-restart command received`));let r=await ge();r.success?console.log(h.default.green(` \u2705 Gateway restarted: ${r.message}`)):console.log(h.default.red(` \u274C Gateway restart failed: ${r.message}`));try{await E(),console.log(h.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(h.default.dim(" Could not push heartbeat."))}}else if((n.type==="bot.delete"||n.type==="bot.disconnect")&&n.bot_user_id){let r=n.bot_user_id,a=n.type==="bot.delete"?"deleted":"disconnected",c=n.type==="bot.delete"?"\u{1F5D1}\uFE0F ":"\u{1F50C}";console.log(h.default.yellow(`
117
+ ${c} Bot ${a}: ${r} \u2014 removing from OpenClaw config...`));try{let{changed:l}=ze(r);l?(console.log(h.default.green(" \u2705 Removed from openclaw.json")),Ke()?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(n.type==="claude_code.start"&&n.bot_id&&n.room_id){console.log(h.default.cyan(`
118
+ \u{1F916} Claude Code START received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await W({id:n.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:n.bot_id,room_id:n.room_id,session_id:n.session_id}});if(console.log(r.success?h.default.green(` \u2705 ${r.message}`):h.default.red(` \u274C ${r.message}`)),n.command_id)try{await k().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await E()}catch{}}catch(r){console.log(h.default.red(` Claude Code start error: ${r.message}`))}}else if(n.type==="claude_code.stop"&&n.bot_id&&n.room_id){console.log(h.default.cyan(`
119
+ \u{1F916} Claude Code STOP received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await W({id:n.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:n.bot_id,room_id:n.room_id,session_id:n.session_id}});if(console.log(r.success?h.default.green(` \u2705 ${r.message}`):h.default.red(` \u274C ${r.message}`)),n.command_id)try{await k().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await E()}catch{}}catch(r){console.log(h.default.red(` Claude Code stop error: ${r.message}`))}}else if(n.type==="command.execute"&&n.command_id){console.log(h.default.cyan(`
120
+ \u26A1 SSE command received: ${n.command_type} (${n.command_id})`));try{let r=k();await r.post(`/api/v1/dashboard/commands/${n.command_id}/ack`);let a=await W({id:n.command_id,command_type:n.command_type,payload:n.payload});console.log(a.success?h.default.green(` \u2705 ${a.message}`):h.default.red(` \u274C ${a.message}`)),await r.post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:a.success?"success":"failed",result:a.message,new_version:a.newVersion||null});try{await E()}catch{}n.command_type==="update_cli"&&a.success&&(console.log(h.default.cyan(" CLI updated \u2014 restarting in 2s...")),setTimeout(()=>process.exit(0),2e3))}catch(r){console.log(h.default.red(` Command ${n.command_id} error: ${r.message}`))}}}catch{}},o.onerror=()=>{console.log(h.default.dim(" Reconnecting..."))},await new Promise(()=>{})});var an=require("commander"),g=i(require("chalk")),V=require("child_process"),$=i(require("fs")),Oe=i(require("os")),Y=i(require("path"));var sn=i(require("fs")),Ft=i(require("os")),pe=i(require("path")),Mt=require("child_process"),K=i(require("chalk"));var Es=`${O}/api/v1/dashboard/versions/latest`,Os=2500,Ds=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),nn=pe.default.join(Ft.default.homedir(),".openclaw/extensions/badgerclaw"),Ns=pe.default.join(Ft.default.homedir(),".openclaw/npm/node_modules/@badgerclaw/connect"),Ts=[pe.default.join(Ns,"package.json"),pe.default.join(nn,"node_modules/@badgerclaw/connect/package.json"),pe.default.join(nn,"package.json")];function Ut(){return"0.2.50"}function js(){for(let e of Ts)try{let t=sn.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 Ls(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function rt(){if((0,Mt.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,Mt.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:Ls(t.stdout)||null}async function Bs(){let e=new AbortController,t=setTimeout(()=>e.abort(),Os);try{let o=await fetch(Es,{signal:e.signal});if(!o.ok)return null;let s=await o.json(),n=s.result&&typeof s.result=="object"?s.result:s;return{cli:n.cli??"unknown",plugin:n.plugin??"unknown",supported_openclaw:n.supported_openclaw??"unknown"}}catch{return null}finally{clearTimeout(t)}}function Ms(e){let t=[];if(e.cli&&e.cli!=="unknown"){let o=Ut();o!==e.cli&&t.push({component:"cli",current:o,approved:e.cli})}if(e.plugin&&e.plugin!=="unknown"){let o=js();(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=rt();(o===null||o!==e.supported_openclaw)&&t.push({component:"openclaw",current:o??"not installed",approved:e.supported_openclaw})}return t}function Fs(e){return e[2]}function Us(e){return!e||e.startsWith("-")?!0:Ds.has(e)}function Gs(e){let t=[];t.push(""),t.push(K.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let s=o.component.padEnd(8);t.push(` ${s} ${K.default.yellow(o.current)} \u2192 ${K.default.green(o.approved)} ${K.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(K.default.green(" To fix, run:")),t.push(K.default.green.bold(" badgerclaw setup")),t.push(""),t.push(K.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
121
+ `)}async function rn(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=Fs(e);if(Us(t))return;let o=await Bs();if(!o)return;let s=Ms(o);s.length!==0&&(process.stderr.write(Gs(s)),process.exit(1))}var N=Y.default.join(Oe.default.homedir(),".openclaw","openclaw.json"),Ee=N+".badgerclaw-stash",at=Y.default.join(Oe.default.homedir(),".openclaw","npm"),Gt=Y.default.join(at,"package.json");async function Ws(){try{let e=await fetch(`${O}/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,s=n=>typeof n!="string"||!n||n==="unknown"?null:n;return{cli:s(o.cli),plugin:s(o.plugin),openclaw:s(o.supported_openclaw)}}catch{return{cli:null,plugin:null,openclaw:null}}}function Vs(){if(!$.default.existsSync(N))return null;try{let e=JSON.parse($.default.readFileSync(N,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,$.default.writeFileSync(N,JSON.stringify(e,null,2)),$.default.writeFileSync(Ee,JSON.stringify(t,null,2)),t):null}catch{return null}}function qs(){if(!$.default.existsSync(N))return null;try{let e=JSON.parse($.default.readFileSync(N,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function Hs(e){if(e&&$.default.existsSync(N))try{let t=JSON.parse($.default.readFileSync(N,"utf-8"));t.gateway={...e,...t.gateway||{}},$.default.writeFileSync(N,JSON.stringify(t,null,2))}catch(t){console.log(g.default.yellow(` \u26A0\uFE0F Could not restore gateway block: ${t.message}`)),console.log(g.default.yellow(" Run `openclaw config set gateway.mode local` manually if the gateway fails to start."))}}function Js(){if($.default.existsSync(Ee))try{let e=JSON.parse($.default.readFileSync(Ee,"utf-8")),t=JSON.parse($.default.readFileSync(N,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,$.default.writeFileSync(N,JSON.stringify(t,null,2)),$.default.unlinkSync(Ee)}catch(e){console.log(g.default.yellow(` \u26A0\uFE0F Could not restore config: ${e.message}`)),console.log(g.default.yellow(` Your bot credentials are backed up at: ${Ee}`))}}async function zs(e){return new Promise(t=>{let o=(0,V.spawn)("openclaw",["plugins","install",e,"--force","--dangerously-force-unsafe-install"],{stdio:["ignore","pipe","pipe"],shell:!0}),s="",n=!1,r=!1,a=/Installed plugin:|Restart the gateway to load plugins/,c=()=>{n||r||(n=!0,setTimeout(()=>{if(!r){try{o.kill("SIGTERM")}catch{}setTimeout(()=>{if(!r)try{o.kill("SIGKILL")}catch{}},1e3)}},3e3))},l=(m,d)=>{d.write(m),s+=m.toString("utf-8"),a.test(s)&&c()};o.stdout.on("data",m=>l(m,process.stdout)),o.stderr.on("data",m=>l(m,process.stderr)),o.on("exit",m=>{r=!0,t({status:n?0:m??1})}),o.on("error",m=>{r||(r=!0,console.error(g.default.red(` openclaw spawn error: ${m.message}`)),t({status:1}))})})}function Ks(){if(!$.default.existsSync(Gt))return!1;let e;try{e=JSON.parse($.default.readFileSync(Gt,"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(Gt,JSON.stringify(e,null,2)+`
122
+ `),!0):!1}var cn=new an.Command("setup").description("Install or update the OpenClaw BadgerClaw plugin safely (handles config automatically)").action(async()=>{console.log(g.default.green(`
122
123
  \u{1F9A1} BadgerClaw Setup
123
- `));let e=await Ms();if(e.cli){let i=jt();i!==e.cli?(console.log(u.default.dim(` Updating CLI: ${i} \u2192 ${e.cli} (supported)...`)),(0,Ae.spawnSync)("npm",["install","-g",`badgerclaw@${e.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 ${e.cli}`))):console.log(u.default.dim(` CLI already at approved version ${i}.`))}if(e.openclaw){let i=nt();i!==e.openclaw?(console.log(i===null?u.default.dim(` Installing OpenClaw ${e.openclaw} (supported)...`):u.default.dim(` Updating OpenClaw: ${i} \u2192 ${e.openclaw} (supported)...`)),(0,Ae.spawnSync)("npm",["install","-g",`openclaw@${e.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 ${e.openclaw}`))):console.log(u.default.dim(` OpenClaw already at approved version ${i}.`))}else nt()===null&&(console.log(u.default.yellow(" \u26A0\uFE0F No approved OpenClaw version and none installed \u2014 installing latest from npm.")),(0,Ae.spawnSync)("npm",["install","-g","openclaw"],{stdio:"inherit",shell:!0}).status!==0&&(console.log(u.default.red(`
124
- \u274C OpenClaw install failed.`)),process.exit(1)));let t=Us();t&&console.log(u.default.dim(" Existing bot config stashed temporarily..."));let o=Fs(),s=Bt.default.join(Lt.default.homedir(),".openclaw","extensions","badgerclaw");if(v.default.existsSync(s))try{v.default.rmSync(s,{recursive:!0,force:!0}),console.log(u.default.dim(" Cleared existing plugin directory."))}catch(i){console.log(u.default.yellow(` \u26A0\uFE0F Could not clear plugin directory (${i.message}); install may fail.`))}let n=e.plugin?`@badgerclaw/connect@${e.plugin}`:"@badgerclaw/connect";e.plugin?console.log(u.default.dim(` Installing ${n} (supported)...`)):console.log(u.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let r=(0,Ae.spawnSync)("openclaw",["plugins","install",n,"--dangerously-force-unsafe-install"],{stdio:"inherit",shell:!0});t&&(Vs(),console.log(u.default.dim(" Bot config restored."))),o&&(Gs(o),console.log(u.default.dim(" Gateway config restored."))),r.status!==0&&(console.log(u.default.red(`
125
- \u274C Plugin install failed. Your bot config has been restored.`)),process.exit(1)),console.log(u.default.green(`
126
- \u2705 BadgerClaw plugin installed successfully!`)),console.log(""),Ge({verbose:!0}).ok||(console.log(u.default.red(`
127
- \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.")),Ve()});var an=require("commander"),$=c(require("chalk"));var cn=new an.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{h()||(console.log($.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=ee(),o=Te(),s=await xe();console.log($.default.bold.green(`
124
+ `));let e=await Ws();if(e.cli){let d=Ut();d!==e.cli?(console.log(g.default.dim(` Updating CLI: ${d} \u2192 ${e.cli} (supported)...`)),(0,V.spawnSync)("npm",["install","-g",`badgerclaw@${e.cli}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(g.default.red("\n\u274C CLI update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(g.default.green(` \u2705 CLI updated to ${e.cli}`))):console.log(g.default.dim(` CLI already at approved version ${d}.`))}if(e.openclaw){let d=rt();d!==e.openclaw?(console.log(d===null?g.default.dim(` Installing OpenClaw ${e.openclaw} (supported)...`):g.default.dim(` Updating OpenClaw: ${d} \u2192 ${e.openclaw} (supported)...`)),(0,V.spawnSync)("npm",["install","-g",`openclaw@${e.openclaw}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(g.default.red("\n\u274C OpenClaw install/update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(g.default.green(` \u2705 OpenClaw at ${e.openclaw}`))):console.log(g.default.dim(` OpenClaw already at approved version ${d}.`))}else rt()===null&&(console.log(g.default.yellow(" \u26A0\uFE0F No approved OpenClaw version and none installed \u2014 installing latest from npm.")),(0,V.spawnSync)("npm",["install","-g","openclaw"],{stdio:"inherit",shell:!0}).status!==0&&(console.log(g.default.red(`
125
+ \u274C OpenClaw install failed.`)),process.exit(1)));let t=Vs();t&&console.log(g.default.dim(" Existing bot config stashed temporarily..."));let o=qs();(0,V.spawnSync)("openclaw",["gateway","stop"],{stdio:"pipe",shell:!0,timeout:1e4});let s=[Y.default.join(Oe.default.homedir(),".openclaw","extensions","badgerclaw"),Y.default.join(Oe.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect")],n=[],r=[],a=d=>{let f=`${d}.bc-setup-stash-${Date.now()}-${Math.floor(Math.random()*1e6)}`,I=(0,V.spawnSync)("mv",["-f",d,f],{encoding:"utf-8"});return I.status===0?{ok:!0,stash:f}:{ok:!1,error:(I.stderr||"").trim()||`exit ${I.status}`}};for(let d of s)if($.default.existsSync(d))try{$.default.rmSync(d,{recursive:!0,force:!0}),n.push(d)}catch(f){let I=a(d);I.ok?(r.push(`${d} \u2192 ${I.stash}`),console.log(g.default.yellow(` \u26A0\uFE0F Could not delete ${d} (${f.message}); renamed it aside instead.`))):(console.log(g.default.red(` \u274C Could not delete ${d} (${f.message})`)),console.log(g.default.red(` Could not rename ${d} aside either (${I.error}). Plugin install will likely fail.`)))}n.length>0&&console.log(g.default.dim(` Cleared existing plugin director${n.length>1?"ies":"y"}.`)),r.length>0&&console.log(g.default.dim(` Renamed busy install${r.length>1?"s":""} aside: ${r.join(", ")}`));let c=e.plugin?`@badgerclaw/connect@${e.plugin}`:"@badgerclaw/connect";e.plugin?console.log(g.default.dim(` Installing ${c} (supported)...`)):console.log(g.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let l=await zs(c);if(t&&(Js(),console.log(g.default.dim(" Bot config restored."))),o&&(Hs(o),console.log(g.default.dim(" Gateway config restored."))),l.status!==0&&(console.log(g.default.red(`
126
+ \u274C Plugin install failed. Your bot config has been restored.`)),process.exit(1)),console.log(g.default.green(`
127
+ \u2705 BadgerClaw plugin installed successfully!`)),Ks()){console.log(g.default.dim(" Stripping OpenClaw uuid:14 override (breaks request@2.88 in matrix-bot-sdk)..."));try{$.default.rmSync(Y.default.join(at,"node_modules","uuid"),{recursive:!0,force:!0})}catch{}try{$.default.rmSync(Y.default.join(at,"package-lock.json"),{force:!0})}catch{}(0,V.spawnSync)("npm",["install"],{cwd:at,stdio:"inherit",shell:!0}).status!==0&&(console.log(g.default.red(`
128
+ \u274C npm install failed after removing uuid override. Bot will not reply correctly until this is resolved.`)),process.exit(1)),console.log(g.default.green(" \u2705 uuid override stripped + npm tree re-resolved."))}console.log(""),qe({verbose:!0}).ok||(console.log(g.default.red(`
129
+ \u274C Gateway failed to start. Diagnose with:`)),console.log(g.default.dim(" systemctl --user status openclaw-gateway.service # Linux")),console.log(g.default.dim(" launchctl list | grep openclaw # macOS")),console.log(g.default.dim(" openclaw config get gateway.mode")),console.log(g.default.dim(" Then re-run `badgerclaw setup` after fixing the underlying issue.")),process.exit(1)),console.log(g.default.green(" \u2705 Gateway is running.")),console.log(g.default.dim("\nNext: run `badgerclaw login` to authenticate.")),He()});var dn=require("commander"),C=i(require("chalk"));var un=new dn.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{_()||(console.log(C.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=ne(),o=Le(),s=await Re();console.log(C.default.bold.green(`
128
130
  BadgerClaw Dashboard
129
- `)),console.log($.default.bold(" Instance")),console.log(` ID: ${N()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${s.pluginVersion}`),console.log(),console.log($.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${rn(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let n=s.status==="running"?$.default.green:s.status==="error"?$.default.red:$.default.yellow;if(console.log($.default.bold(" Gateway")),console.log(` Status: ${n(s.status)}`),console.log(` PID: ${s.pid??"N/A"}`),console.log(` Last Restart: ${s.lastRestart??"N/A"}`),console.log(),s.bots.length===0)console.log($.default.bold(" Bots")),console.log($.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log($.default.bold(` Bots (${s.bots.length})`)),console.log();for(let r of s.bots){let a=r.status==="running"?$.default.green:r.status==="error"?$.default.red:$.default.yellow;if(console.log(` ${$.default.bold(r.botUsername)} ${a(`[${r.status}]`)}`),console.log(` ID: ${r.botId}`),console.log(` Uptime: ${rn(r.uptimeSeconds)}`),console.log(` Messages: ${r.messagesReceived} in / ${r.messagesSent} out`),r.chunkedMessages>0&&console.log(` Chunked: ${r.chunkedMessages} messages, ${r.totalChunksSent} chunks`),console.log(` Rooms: ${r.roomsActive} active`),console.log(` Errors: ${r.errors}`),r.lastError&&(console.log(` Last Error: ${$.default.red(r.lastError)}`),console.log(` Error At: ${r.lastErrorAt}`)),console.log(` Last Active: ${r.lastActivity??"N/A"}`),r.roomDetails&&r.roomDetails.length>0){console.log($.default.dim(" Rooms:"));for(let i of r.roomDetails)console.log($.default.dim(` ${i.roomName} \u2014 ${i.messagesInRoom} msgs, last: ${i.lastActivityInRoom??"N/A"}`))}console.log()}}console.log($.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function rn(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 Mt=require("commander"),me=c(require("chalk")),ln=c(require("ora"));var Ws=new Mt.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{h()||(console.log(me.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,ln.default)("Restarting gateway...").start(),o=await de();if(o.success){t.succeed(me.default.green(`Gateway restarted: ${o.message}`));try{await P(),console.log(me.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(me.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(me.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),dn=new Mt.Command("gateway").description("Manage the OpenClaw gateway").addCommand(Ws);var Y=require("commander"),p=c(require("chalk")),ne=c(require("ora")),z=c(require("axios"));Xe();var oe="http://localhost:7331",qs=new Y.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=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=e.sessionId||`session-${Date.now()}`,s=parseInt(e.port,10),n=e.project.replace(/^~/,process.env.HOME||""),r=(0,ne.default)("Starting Claude Code session...").start();try{await z.default.post(`${oe}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),r.text="Gateway toggled \u2014 launching MCP server...";let i=At({sessionId:o,port:s,projectDir:n}).pid||0;await new Promise(l=>setTimeout(l,1500)),r.text="MCP server running \u2014 launching Claude Code...",Rt({sessionId:o,port:s,projectDir:n}),Pt(o,0,i,s,n),r.succeed(p.default.green("Claude Code session started")+p.default.dim(` (session: ${o}, port: ${s})`)),console.log(p.default.dim(` Bot: ${e.bot}`)),console.log(p.default.dim(` Room: ${e.room}`)),console.log(p.default.dim(` Project: ${n}`)),console.log(p.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let i=a.response?.data?.message||a.message||"Unknown error";r.fail(p.default.red(`Failed to start Claude Code: ${i}`)),process.exit(1)}}),Hs=new Y.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=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,ne.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await z.default.post(`${oe}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let s=e.sessionId;if(!s)try{let a=((await z.default.get(`${oe}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(i=>i.botId===e.bot&&i.roomId===e.room);a&&(s=a.sessionId)}catch{}s?(Et(s),o.succeed(p.default.green(`Claude Code session stopped (${s})`))):(o.succeed(p.default.green("Claude Code toggled off at gateway")),console.log(p.default.dim(" No local session found to kill \u2014 may need to close Claude Code manually.")))}catch(s){let n=s.response?.data?.message||s.message||"Unknown error";o.fail(p.default.red(`Failed to stop Claude Code: ${n}`)),process.exit(1)}}),Js=new Y.Command("status").description("Show active Claude Code sessions").action(async()=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,ne.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await z.default.get(`${oe}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let s=Ot();if(t.stop(),o.length===0&&s.length===0){console.log(p.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(p.default.bold(`
130
- Gateway Claude Code Rooms:`)),console.log(p.default.dim(" Bot".padEnd(30)+"Room".padEnd(30)+"Session".padEnd(20)+"Enabled")),console.log(p.default.dim(" "+"-".repeat(88)));for(let n of o){let r=n.enabled?p.default.green("ON"):p.default.dim("OFF");console.log(` ${(n.botId||"").padEnd(30)}${(n.roomName||n.roomId||"").padEnd(30)}${(n.sessionId||"-").padEnd(20)}${r}`)}}if(s.length>0){console.log(p.default.bold(`
131
- Local Sessions:`)),console.log(p.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(p.default.dim(" "+"-".repeat(90)));for(let n of s)console.log(` ${n.sessionId.padEnd(25)}${String(n.port).padEnd(8)}${String(n.mcpPid).padEnd(10)}${n.projectDir.padEnd(40)}${n.startedAt}`)}console.log("")}catch(o){t.fail(p.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),zs=new Y.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,ne.default)("Grouping bot+room into session...").start();try{await z.default.post(`${oe}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:e.session},{timeout:1e4}),t.succeed(p.default.green(`Grouped ${e.bot} + ${e.room} into session "${e.session}"`))}catch(o){let s=o.response?.data?.message||o.message||"Unknown error";t.fail(p.default.red(`Failed to group: ${s}`)),process.exit(1)}}),Ys=new Y.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,ne.default)("Adding user to allowlist...").start();try{await z.default.post(`${oe}/claude-code/allow`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(p.default.green(`Added ${e.user} to allowlist for ${e.bot} in ${e.room}`))}catch(o){let s=o.response?.data?.message||o.message||"Unknown error";t.fail(p.default.red(`Failed to add user: ${s}`)),process.exit(1)}}),Ks=new Y.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,ne.default)("Removing user from allowlist...").start();try{await z.default.post(`${oe}/claude-code/revoke`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(p.default.green(`Removed ${e.user} from allowlist for ${e.bot} in ${e.room}`))}catch(o){let s=o.response?.data?.message||o.message||"Unknown error";t.fail(p.default.red(`Failed to revoke user: ${s}`)),process.exit(1)}}),un=new Y.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(qs).addCommand(Hs).addCommand(Js).addCommand(zs).addCommand(Ys).addCommand(Ks);async function Qs(){await on(process.argv);let e=new mn.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.48"),e.addCommand(Io),e.addCommand(Ao),e.addCommand(Po),e.addCommand(Bo),e.addCommand(uo),e.addCommand(Xo),e.addCommand(sn),e.addCommand(Yo),e.addCommand(cn),e.addCommand(dn),e.addCommand(un),e.parse(process.argv)}Qs().catch(e=>{console.error(e),process.exit(1)});
131
+ `)),console.log(C.default.bold(" Instance")),console.log(` ID: ${j()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${s.pluginVersion}`),console.log(),console.log(C.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${ln(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let n=s.status==="running"?C.default.green:s.status==="error"?C.default.red:C.default.yellow;if(console.log(C.default.bold(" Gateway")),console.log(` Status: ${n(s.status)}`),console.log(` PID: ${s.pid??"N/A"}`),console.log(` Last Restart: ${s.lastRestart??"N/A"}`),console.log(),s.bots.length===0)console.log(C.default.bold(" Bots")),console.log(C.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log(C.default.bold(` Bots (${s.bots.length})`)),console.log();for(let r of s.bots){let a=r.status==="running"?C.default.green:r.status==="error"?C.default.red:C.default.yellow;if(console.log(` ${C.default.bold(r.botUsername)} ${a(`[${r.status}]`)}`),console.log(` ID: ${r.botId}`),console.log(` Uptime: ${ln(r.uptimeSeconds)}`),console.log(` Messages: ${r.messagesReceived} in / ${r.messagesSent} out`),r.chunkedMessages>0&&console.log(` Chunked: ${r.chunkedMessages} messages, ${r.totalChunksSent} chunks`),console.log(` Rooms: ${r.roomsActive} active`),console.log(` Errors: ${r.errors}`),r.lastError&&(console.log(` Last Error: ${C.default.red(r.lastError)}`),console.log(` Error At: ${r.lastErrorAt}`)),console.log(` Last Active: ${r.lastActivity??"N/A"}`),r.roomDetails&&r.roomDetails.length>0){console.log(C.default.dim(" Rooms:"));for(let c of r.roomDetails)console.log(C.default.dim(` ${c.roomName} \u2014 ${c.messagesInRoom} msgs, last: ${c.lastActivityInRoom??"N/A"}`))}console.log()}}console.log(C.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function ln(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 Wt=require("commander"),fe=i(require("chalk")),mn=i(require("ora"));var Ys=new Wt.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{_()||(console.log(fe.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,mn.default)("Restarting gateway...").start(),o=await ge();if(o.success){t.succeed(fe.default.green(`Gateway restarted: ${o.message}`));try{await E(),console.log(fe.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(fe.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(fe.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),gn=new Wt.Command("gateway").description("Manage the OpenClaw gateway").addCommand(Ys);var X=require("commander"),w=i(require("chalk")),ie=i(require("ora")),Q=i(require("axios"));tt();var ae="http://localhost:7331",Qs=new X.Command("start").description("Start a Claude Code session for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID (default: auto-generated)").option("--port <port>","MCP server port (default: 7332)","7332").option("--project <dir>","Project directory",process.cwd()).action(async e=>{_()||(console.log(w.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=e.sessionId||`session-${Date.now()}`,s=parseInt(e.port,10),n=e.project.replace(/^~/,process.env.HOME||""),r=(0,ie.default)("Starting Claude Code session...").start();try{await Q.default.post(`${ae}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),r.text="Gateway toggled \u2014 launching MCP server...";let c=Ot({sessionId:o,port:s,projectDir:n}).pid||0;await new Promise(l=>setTimeout(l,1500)),r.text="MCP server running \u2014 launching Claude Code...",Dt({sessionId:o,port:s,projectDir:n}),Nt(o,0,c,s,n),r.succeed(w.default.green("Claude Code session started")+w.default.dim(` (session: ${o}, port: ${s})`)),console.log(w.default.dim(` Bot: ${e.bot}`)),console.log(w.default.dim(` Room: ${e.room}`)),console.log(w.default.dim(` Project: ${n}`)),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";r.fail(w.default.red(`Failed to start Claude Code: ${c}`)),process.exit(1)}}),Xs=new X.Command("stop").description("Stop a Claude Code session").option("--bot <botId>","Bot ID or username").option("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID to stop").action(async e=>{_()||(console.log(w.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,ie.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await Q.default.post(`${ae}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let s=e.sessionId;if(!s)try{let a=((await Q.default.get(`${ae}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(c=>c.botId===e.bot&&c.roomId===e.room);a&&(s=a.sessionId)}catch{}s?(Tt(s),o.succeed(w.default.green(`Claude Code session stopped (${s})`))):(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(s){let n=s.response?.data?.message||s.message||"Unknown error";o.fail(w.default.red(`Failed to stop Claude Code: ${n}`)),process.exit(1)}}),Zs=new X.Command("status").description("Show active Claude Code sessions").action(async()=>{_()||(console.log(w.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,ie.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await Q.default.get(`${ae}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let s=jt();if(t.stop(),o.length===0&&s.length===0){console.log(w.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(w.default.bold(`
132
+ 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 n of o){let r=n.enabled?w.default.green("ON"):w.default.dim("OFF");console.log(` ${(n.botId||"").padEnd(30)}${(n.roomName||n.roomId||"").padEnd(30)}${(n.sessionId||"-").padEnd(20)}${r}`)}}if(s.length>0){console.log(w.default.bold(`
133
+ 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 n of s)console.log(` ${n.sessionId.padEnd(25)}${String(n.port).padEnd(8)}${String(n.mcpPid).padEnd(10)}${n.projectDir.padEnd(40)}${n.startedAt}`)}console.log("")}catch(o){t.fail(w.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),er=new X.Command("group").description("Group bots/rooms into a shared Claude Code session").requiredOption("--session <id>","Session ID to group under").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").action(async e=>{let t=(0,ie.default)("Grouping bot+room into session...").start();try{await Q.default.post(`${ae}/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 s=o.response?.data?.message||o.message||"Unknown error";t.fail(w.default.red(`Failed to group: ${s}`)),process.exit(1)}}),tr=new X.Command("allow").description("Add a user to the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to allow (e.g. @alice:server)").action(async e=>{let t=(0,ie.default)("Adding user to allowlist...").start();try{await Q.default.post(`${ae}/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 s=o.response?.data?.message||o.message||"Unknown error";t.fail(w.default.red(`Failed to add user: ${s}`)),process.exit(1)}}),or=new X.Command("revoke").description("Remove a user from the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to revoke").action(async e=>{let t=(0,ie.default)("Removing user from allowlist...").start();try{await Q.default.post(`${ae}/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 s=o.response?.data?.message||o.message||"Unknown error";t.fail(w.default.red(`Failed to revoke user: ${s}`)),process.exit(1)}}),pn=new X.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(Qs).addCommand(Xs).addCommand(Zs).addCommand(er).addCommand(tr).addCommand(or);async function nr(){await rn(process.argv);let e=new fn.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.50"),e.addCommand(Ro),e.addCommand(Oo),e.addCommand(No),e.addCommand(Go),e.addCommand(fo),e.addCommand(on),e.addCommand(cn),e.addCommand(Zo),e.addCommand(un),e.addCommand(gn),e.addCommand(pn),e.parse(process.argv)}nr().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.48",
3
+ "version": "0.2.50",
4
4
  "description": "BadgerClaw CLI — one-click bot provisioning",
5
5
  "main": "dist/index.js",
6
6
  "bin": {