badgerclaw 0.2.40 → 0.2.42

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