badgerclaw 0.2.18 → 0.2.19

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 +24 -23
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var wo=Object.create;var he=Object.defineProperty;var _o=Object.getOwnPropertyDescriptor;var bo=Object.getOwnPropertyNames;var $o=Object.getPrototypeOf,So=Object.prototype.hasOwnProperty;var Co=(e,t)=>()=>(e&&(t=e(e=0)),t);var vo=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Io=(e,t)=>{for(var o in t)he(e,o,{get:t[o],enumerable:!0})},mt=(e,t,o,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of bo(t))!So.call(e,n)&&n!==o&&he(e,n,{get:()=>t[n],enumerable:!(s=_o(t,n))||s.enumerable});return e};var c=(e,t,o)=>(o=e!=null?wo($o(e)):{},mt(t||!e||!e.__esModule?he(o,"default",{value:e,enumerable:!0}):o,e)),ut=e=>mt(he({},"__esModule",{value:!0}),e);var W=vo((Qs,Uo)=>{Uo.exports={name:"badgerclaw",version:"0.2.18",description:"BadgerClaw CLI \u2014 one-click bot provisioning",main:"dist/index.js",bin:{badgerclaw:"./dist/index.js"},files:["dist/","README.md"],scripts:{build:"node build.mjs",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 it={};Io(it,{getActiveSessions:()=>at,launchClaudeCode:()=>st,launchMCPServer:()=>ot,recordSession:()=>nt,stopSession:()=>rt});function Qe(){try{if(v.default.existsSync(Xe))return JSON.parse(v.default.readFileSync(Xe,"utf-8"))}catch{}return[]}function Ze(e){v.default.mkdirSync(J,{recursive:!0}),v.default.writeFileSync(Xe,JSON.stringify(e,null,2))}function Re(e){try{return process.kill(e,0),!0}catch{return!1}}function zo(){if(process.env.TMUX)return"tmux";try{if((0,F.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),v.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function et(e,t){let o=R.default.join(J,`claude-launcher-${t}.exp`),s=R.default.join(J,`pending-input-${t}.txt`);v.default.writeFileSync(s,"","utf-8");let n=`#!/usr/bin/expect -f
2
+ "use strict";var Co=Object.create;var he=Object.defineProperty;var vo=Object.getOwnPropertyDescriptor;var Io=Object.getOwnPropertyNames;var ko=Object.getPrototypeOf,xo=Object.prototype.hasOwnProperty;var Ao=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ro=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Po=(e,t)=>{for(var o in t)he(e,o,{get:t[o],enumerable:!0})},mt=(e,t,o,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Io(t))!xo.call(e,n)&&n!==o&&he(e,n,{get:()=>t[n],enumerable:!(s=vo(t,n))||s.enumerable});return e};var c=(e,t,o)=>(o=e!=null?Co(ko(e)):{},mt(t||!e||!e.__esModule?he(o,"default",{value:e,enumerable:!0}):o,e)),gt=e=>mt(he({},"__esModule",{value:!0}),e);var M=Ro((hn,Wo)=>{Wo.exports={name:"badgerclaw",version:"0.2.19",description:"BadgerClaw CLI \u2014 one-click bot provisioning",main:"dist/index.js",bin:{badgerclaw:"./dist/index.js"},files:["dist/","README.md"],scripts:{build:"node build.mjs",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 ct={};Po(ct,{getActiveSessions:()=>it,launchClaudeCode:()=>nt,launchMCPServer:()=>st,recordSession:()=>rt,stopSession:()=>at});function Ze(){try{if(I.default.existsSync(Qe))return JSON.parse(I.default.readFileSync(Qe,"utf-8"))}catch{}return[]}function et(e){I.default.mkdirSync(q,{recursive:!0}),I.default.writeFileSync(Qe,JSON.stringify(e,null,2))}function Pe(e){try{return process.kill(e,0),!0}catch{return!1}}function Zo(){if(process.env.TMUX)return"tmux";try{if((0,F.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),I.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function tt(e,t){let o=P.default.join(q,`claude-launcher-${t}.exp`),s=P.default.join(q,`pending-input-${t}.txt`);I.default.writeFileSync(s,"","utf-8");let n=`#!/usr/bin/expect -f
3
3
  set timeout -1
4
4
  set msgfile "${s}"
5
5
 
@@ -36,7 +36,7 @@ send "\\r"
36
36
  interact timeout 2 {
37
37
  check_and_send_messages
38
38
  }
39
- `;return v.default.mkdirSync(J,{recursive:!0}),v.default.writeFileSync(o,n,{mode:493}),o}function tt(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function Yo(e,t,o){let s=et(e,o.BADGERCLAW_SESSION_ID||"default"),n=tt(o),r=`
39
+ `;return I.default.mkdirSync(q,{recursive:!0}),I.default.writeFileSync(o,n,{mode:493}),o}function ot(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function es(e,t,o){let s=tt(e,o.BADGERCLAW_SESSION_ID||"default"),n=ot(o),r=`
40
40
  tell application "iTerm"
41
41
  activate
42
42
  set newWindow to (create window with default profile)
@@ -44,20 +44,20 @@ interact timeout 2 {
44
44
  write text "cd ${Ee(t)} && ${n} && ${Ee(s)}"
45
45
  end tell
46
46
  end tell
47
- `;(0,F.execSync)(`osascript -e '${r.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Ko(e,t,o){let s=et(e,o.BADGERCLAW_SESSION_ID||"default"),n=tt(o),a=`
47
+ `;(0,F.execSync)(`osascript -e '${r.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function ts(e,t,o){let s=tt(e,o.BADGERCLAW_SESSION_ID||"default"),n=ot(o),a=`
48
48
  tell application "Terminal"
49
49
  activate
50
50
  do script "${`cd ${Ee(t)} && ${n} && ${Ee(s)}`.replace(/"/g,'\\"')}"
51
51
  end tell
52
- `;(0,F.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Xo(e,t,o){let s=et(e,o.BADGERCLAW_SESSION_ID||"default"),n=tt(o),r=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${n} && ${s}`;(0,F.execSync)(`tmux new-session -d -s ${r} "${a}"`,{stdio:"pipe",timeout:1e4})}function Ee(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function ot(e){let t=R.default.join(__dirname,"..","claude-code","mcp-server.js"),o=v.default.existsSync(t)?t:R.default.join(__dirname,"mcp-server.js"),s=(0,F.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 st(e){let t=R.default.join(R.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=R.default.join(__dirname,"..","claude-code","mcp-server.js"),s=R.default.join(__dirname,"mcp-server.js"),n=v.default.existsSync(t)?t:v.default.existsSync(o)?o:s,r={BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},a=JSON.stringify({mcpServers:{badgerclaw:{command:"node",args:[n],env:r}}}),i=R.default.join(J,`mcp-config-${e.sessionId}.json`);v.default.mkdirSync(J,{recursive:!0}),v.default.writeFileSync(i,a,"utf-8");let l=`claude --dangerously-skip-permissions --mcp-config ${i}`;switch(zo()){case"iterm2":Yo(l,e.projectDir,r);break;case"terminal":Ko(l,e.projectDir,r);break;case"tmux":Xo(l,e.projectDir,r);break;case"direct":(0,F.spawn)(l,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...r},stdio:"ignore",detached:!0}).unref();break}}function nt(e,t,o,s,n){let r=Qe().filter(a=>a.sessionId!==e);r.push({sessionId:e,pid:t,mcpPid:o,port:s,projectDir:n,startedAt:new Date().toISOString()}),Ze(r)}function rt(e){let t=Qe(),o=t.find(n=>n.sessionId===e);if(!o)return!1;if(o.mcpPid&&Re(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&Re(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,F.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let s=t.filter(n=>n.sessionId!==e);return Ze(s),!0}function at(){let e=Qe(),t=e.filter(o=>Re(o.mcpPid)||Re(o.pid));return t.length!==e.length&&Ze(t),t}var F,v,R,Yt,J,Xe,De=Co(()=>{"use strict";F=require("child_process"),v=c(require("fs")),R=c(require("path")),Yt=c(require("os")),J=R.default.join(Yt.default.homedir(),".badgerclaw"),Xe=R.default.join(J,"claude-sessions.json")});var yo=require("commander");var jt=require("commander"),q=c(require("chalk")),Bt=c(require("ora")),Lt=c(require("open")),X=c(require("os")),Ut=c(require("crypto"));var je=c(require("crypto"));function gt(){return je.default.randomBytes(32).toString("base64url")}function pt(e){return je.default.createHash("sha256").update(e).digest("base64url")}var te=c(require("fs")),Be=c(require("path")),ft=c(require("os")),ht=Be.default.join(ft.default.homedir(),".badgerclaw"),Le=Be.default.join(ht,"auth.json");function h(){try{let e=te.default.readFileSync(Le,"utf-8");return JSON.parse(e)}catch{return null}}function ye(e){te.default.mkdirSync(ht,{recursive:!0}),te.default.writeFileSync(Le,JSON.stringify(e,null,2),{mode:384})}function yt(){try{te.default.unlinkSync(Le)}catch{}}function we(){let e=h();return e?new Date(e.expires_at)>new Date:!1}function _e(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var oe=c(require("axios"));var wt=process.env.BADGERCLAW_ENV==="local",U=process.env.BADGERCLAW_API_URL??(wt?"http://localhost:8000":"https://api.badger.signout.io"),_t=process.env.BADGERCLAW_AUTH_URL??(wt?"http://localhost:5500":"https://badgerclaw.ai");var $e=U,be=null;async function Ue(){let e=h();if(!e?.refresh_token||!e?.email)return null;try{let t=await oe.default.post(`${$e}/api/v1/user/token/refresh`,{refresh_token:e.refresh_token,email:e.email}),o=t.data?.result??t.data,s=o?.access_token;if(!s)return null;let n=o.expires_in||3600,r=new Date(Date.now()+n*1e3).toISOString();return ye({...e,access_token:s,expires_at:r}),s}catch{return null}}function Me(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 bt(e){return e.interceptors.response.use(void 0,async t=>{let o=t.config;if(t.response?.status!==401||o._retried)return Promise.reject(t);o._retried=!0,be||(be=Ue().finally(()=>{be=null}));let s=await be;return s?(o.headers.Authorization=`Bearer ${s}`,e.request(o)):Promise.reject(t)}),e}function C(){let e=h(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=oe.default.create({baseURL:$e,headers:t});return Me(o),bt(o),o}function $t(){return Me(oe.default.create({baseURL:$e,headers:{"Content-Type":"application/json"}}))}function Se(e){let t=oe.default.create({baseURL:$e,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return Me(t),bt(t),t}var St=require("commander"),j=c(require("chalk")),Fe=c(require("ora")),Ct=c(require("os")),vt=c(require("path"));var Gs=vt.default.join(Ct.default.homedir(),".openclaw","openclaw.json");async function se(e,t,o,s){let n=h();if(!n)return;let r=s?null:(0,Fe.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${U}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e})});if(!a.ok){let E=await a.json().catch(()=>({errors:[a.statusText]}));r?.fail(j.default.red(`Failed to redeem ${t}: ${E.errors?.[0]||a.status}`));return}let i=await a.json(),l=i.result??i,{execSync:m}=await import("child_process"),f=`channels.badgerclaw.accounts.${l.user_id.split(":")[0].replace("@","").replace(/_bot$/,"")}`;m(`openclaw config set ${f}.userId "${l.user_id}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),m(`openclaw config set ${f}.accessToken "${l.access_token}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),m(`openclaw config set ${f}.homeserver "${l.homeserver}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),m(`openclaw config set ${f}.encryption true`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),l.device_id&&m(`openclaw config set ${f}.deviceId "${l.device_id}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),await fetch(`${U}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${n.access_token}`}}).catch(()=>{}),r?.succeed(j.default.green(`\u2705 ${l.bot_name} (${l.user_id}) paired \u2014 bot is live!`))}catch(a){r?.fail(j.default.red(`Failed to pair ${t}: ${a.message}`))}}async function ne(e=!1){let t=h();if(!t)return 0;let o=Se(t.access_token);try{let{data:s}=await o.get("/api/v1/openclaw/pending-pairs");if(!s||s.length===0)return 0;let n=new Map;for(let a of s)n.set(a.bot_user_id,a);for(let a of s)n.get(a.bot_user_id)!==a&&await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{});let r=0;for(let a of n.values()){let i=e?null:(0,Fe.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await se(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),r++}catch(l){i?.fail(j.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(j.default.green(`
52
+ `;(0,F.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function os(e,t,o){let s=tt(e,o.BADGERCLAW_SESSION_ID||"default"),n=ot(o),r=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${n} && ${s}`;(0,F.execSync)(`tmux new-session -d -s ${r} "${a}"`,{stdio:"pipe",timeout:1e4})}function Ee(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function st(e){let t=P.default.join(__dirname,"..","claude-code","mcp-server.js"),o=I.default.existsSync(t)?t:P.default.join(__dirname,"mcp-server.js"),s=(0,F.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 nt(e){let t=P.default.join(P.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=P.default.join(__dirname,"..","claude-code","mcp-server.js"),s=P.default.join(__dirname,"mcp-server.js"),n=I.default.existsSync(t)?t:I.default.existsSync(o)?o:s,r={BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},a=JSON.stringify({mcpServers:{badgerclaw:{command:"node",args:[n],env:r}}}),i=P.default.join(q,`mcp-config-${e.sessionId}.json`);I.default.mkdirSync(q,{recursive:!0}),I.default.writeFileSync(i,a,"utf-8");let l=`claude --dangerously-skip-permissions --mcp-config ${i}`;switch(Zo()){case"iterm2":es(l,e.projectDir,r);break;case"terminal":ts(l,e.projectDir,r);break;case"tmux":os(l,e.projectDir,r);break;case"direct":(0,F.spawn)(l,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...r},stdio:"ignore",detached:!0}).unref();break}}function rt(e,t,o,s,n){let r=Ze().filter(a=>a.sessionId!==e);r.push({sessionId:e,pid:t,mcpPid:o,port:s,projectDir:n,startedAt:new Date().toISOString()}),et(r)}function at(e){let t=Ze(),o=t.find(n=>n.sessionId===e);if(!o)return!1;if(o.mcpPid&&Pe(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&Pe(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,F.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let s=t.filter(n=>n.sessionId!==e);return et(s),!0}function it(){let e=Ze(),t=e.filter(o=>Pe(o.mcpPid)||Pe(o.pid));return t.length!==e.length&&et(t),t}var F,I,P,Yt,q,Qe,De=Ao(()=>{"use strict";F=require("child_process"),I=c(require("fs")),P=c(require("path")),Yt=c(require("os")),q=P.default.join(Yt.default.homedir(),".badgerclaw"),Qe=P.default.join(q,"claude-sessions.json")});var So=require("commander");var Lt=require("commander"),J=c(require("chalk")),Bt=c(require("ora")),Ut=c(require("open")),X=c(require("os")),Mt=c(require("crypto"));var Le=c(require("crypto"));function pt(){return Le.default.randomBytes(32).toString("base64url")}function ft(e){return Le.default.createHash("sha256").update(e).digest("base64url")}var te=c(require("fs")),Be=c(require("path")),ht=c(require("os")),wt=Be.default.join(ht.default.homedir(),".badgerclaw"),Ue=Be.default.join(wt,"auth.json");function h(){try{let e=te.default.readFileSync(Ue,"utf-8");return JSON.parse(e)}catch{return null}}function we(e){te.default.mkdirSync(wt,{recursive:!0}),te.default.writeFileSync(Ue,JSON.stringify(e,null,2),{mode:384})}function yt(){try{te.default.unlinkSync(Ue)}catch{}}function ye(){let e=h();return e?new Date(e.expires_at)>new Date:!1}function _e(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var oe=c(require("axios"));var _t=process.env.BADGERCLAW_ENV==="local",A=process.env.BADGERCLAW_API_URL??(_t?"http://localhost:8000":"https://api.badger.signout.io"),bt=process.env.BADGERCLAW_AUTH_URL??(_t?"http://localhost:5500":"https://badgerclaw.ai");var $e=A,be=null;async function Me(){let e=h();if(!e?.refresh_token||!e?.email)return null;try{let t=await oe.default.post(`${$e}/api/v1/user/token/refresh`,{refresh_token:e.refresh_token,email:e.email}),o=t.data?.result??t.data,s=o?.access_token;if(!s)return null;let n=o.expires_in||3600,r=new Date(Date.now()+n*1e3).toISOString();return we({...e,access_token:s,expires_at:r}),s}catch{return null}}function Fe(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 $t(e){return e.interceptors.response.use(void 0,async t=>{let o=t.config;if(t.response?.status!==401||o._retried)return Promise.reject(t);o._retried=!0,be||(be=Me().finally(()=>{be=null}));let s=await be;return s?(o.headers.Authorization=`Bearer ${s}`,e.request(o)):Promise.reject(t)}),e}function v(){let e=h(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=oe.default.create({baseURL:$e,headers:t});return Fe(o),$t(o),o}function St(){return Fe(oe.default.create({baseURL:$e,headers:{"Content-Type":"application/json"}}))}function Se(e){let t=oe.default.create({baseURL:$e,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return Fe(t),$t(t),t}var Ct=require("commander"),j=c(require("chalk")),Ge=c(require("ora")),vt=c(require("os")),It=c(require("path"));var rn=It.default.join(vt.default.homedir(),".openclaw","openclaw.json");async function se(e,t,o,s){let n=h();if(!n)return;let r=s?null:(0,Ge.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${A}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e})});if(!a.ok){let E=await a.json().catch(()=>({errors:[a.statusText]}));r?.fail(j.default.red(`Failed to redeem ${t}: ${E.errors?.[0]||a.status}`));return}let i=await a.json(),l=i.result??i,{execSync:u}=await import("child_process"),f=`channels.badgerclaw.accounts.${l.user_id.split(":")[0].replace("@","").replace(/_bot$/,"")}`;u(`openclaw config set ${f}.userId "${l.user_id}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),u(`openclaw config set ${f}.accessToken "${l.access_token}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),u(`openclaw config set ${f}.homeserver "${l.homeserver}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),u(`openclaw config set ${f}.encryption true`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),l.device_id&&u(`openclaw config set ${f}.deviceId "${l.device_id}"`,{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),await fetch(`${A}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${n.access_token}`}}).catch(()=>{}),r?.succeed(j.default.green(`\u2705 ${l.bot_name} (${l.user_id}) paired \u2014 bot is live!`))}catch(a){r?.fail(j.default.red(`Failed to pair ${t}: ${a.message}`))}}async function ne(e=!1){let t=h();if(!t)return 0;let o=Se(t.access_token);try{let{data:s}=await o.get("/api/v1/openclaw/pending-pairs");if(!s||s.length===0)return 0;let n=new Map;for(let a of s)n.set(a.bot_user_id,a);for(let a of s)n.get(a.bot_user_id)!==a&&await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{});let r=0;for(let a of n.values()){let i=e?null:(0,Ge.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await se(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),r++}catch(l){i?.fail(j.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(j.default.green(`
53
53
  \u26A1 ${r} bot(s) paired \u2014 gateway restarted, bots are live!`))}catch{e||console.log(j.default.yellow(`
54
- \u26A1 ${r} bot(s) paired. Run: openclaw gateway restart`))}return r}catch{return 0}}var It=new St.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!h()){console.log(j.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(j.default.dim("Checking for pending bot pairs...")),await ne(!1)===0&&console.log(j.default.dim("No pending pairs found."))});var O=c(require("chalk")),re=c(require("fs")),ae=c(require("path")),We=c(require("os")),Ge=ae.default.join(We.default.homedir(),".badgerclaw","update-check.json"),xo=1440*60*1e3,ko="https://registry.npmjs.org/badgerclaw/latest",Ao="https://registry.npmjs.org/@badgerclaw%2Fconnect/latest";function Po(){try{return JSON.parse(re.default.readFileSync(Ge,"utf-8"))}catch{return null}}function Ro(e){try{re.default.mkdirSync(ae.default.dirname(Ge),{recursive:!0}),re.default.writeFileSync(Ge,JSON.stringify(e))}catch{}}function Ce(e,t){let o=m=>m.replace(/[^0-9.]/g,"").split(".").map(Number),[s,n,r]=o(e),[a,i,l]=o(t);return a!==s?a>s:i!==n?i>n:l>r}function xt(){try{let e=ae.default.join(We.default.homedir(),".openclaw"),t=ae.default.join(e,"node_modules","@badgerclaw","connect","package.json");return JSON.parse(re.default.readFileSync(t,"utf-8")).version||null}catch{return null}}async function ve(e,t=!1){try{let o=Po(),s=Date.now();if(o&&s-o.lastCheck<xo){if(Ce(e,o.latestVersion)&&kt(e,o.latestVersion),o.latestPluginVersion){let w=xt();w&&Ce(w,o.latestPluginVersion)&&At(w,o.latestPluginVersion)}return}let n=new AbortController,r=setTimeout(()=>n.abort(),3e3),[a,i]=await Promise.allSettled([fetch(ko,{signal:n.signal}),fetch(Ao,{signal:n.signal})]);clearTimeout(r);let l=e,m;if(a.status==="fulfilled"&&a.value.ok&&(l=(await a.value.json()).version),i.status==="fulfilled"&&i.value.ok&&(m=(await i.value.json()).version),Ro({lastCheck:s,latestVersion:l,latestPluginVersion:m}),Ce(e,l)&&kt(e,l),m){let w=xt();w&&Ce(w,m)&&At(w,m)}}catch{}}function kt(e,t){console.log(O.default.yellow(`
54
+ \u26A1 ${r} bot(s) paired. Run: openclaw gateway restart`))}return r}catch{return 0}}var kt=new Ct.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!h()){console.log(j.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(j.default.dim("Checking for pending bot pairs...")),await ne(!1)===0&&console.log(j.default.dim("No pending pairs found."))});var O=c(require("chalk")),re=c(require("fs")),ae=c(require("path")),We=c(require("os")),Ve=ae.default.join(We.default.homedir(),".badgerclaw","update-check.json"),Eo=1440*60*1e3,Do="https://registry.npmjs.org/badgerclaw/latest",No="https://registry.npmjs.org/@badgerclaw%2Fconnect/latest";function To(){try{return JSON.parse(re.default.readFileSync(Ve,"utf-8"))}catch{return null}}function Oo(e){try{re.default.mkdirSync(ae.default.dirname(Ve),{recursive:!0}),re.default.writeFileSync(Ve,JSON.stringify(e))}catch{}}function Ce(e,t){let o=u=>u.replace(/[^0-9.]/g,"").split(".").map(Number),[s,n,r]=o(e),[a,i,l]=o(t);return a!==s?a>s:i!==n?i>n:l>r}function xt(){try{let e=ae.default.join(We.default.homedir(),".openclaw"),t=ae.default.join(e,"node_modules","@badgerclaw","connect","package.json");return JSON.parse(re.default.readFileSync(t,"utf-8")).version||null}catch{return null}}async function ve(e,t=!1){try{let o=To(),s=Date.now();if(o&&s-o.lastCheck<Eo){if(Ce(e,o.latestVersion)&&At(e,o.latestVersion),o.latestPluginVersion){let y=xt();y&&Ce(y,o.latestPluginVersion)&&Rt(y,o.latestPluginVersion)}return}let n=new AbortController,r=setTimeout(()=>n.abort(),3e3),[a,i]=await Promise.allSettled([fetch(Do,{signal:n.signal}),fetch(No,{signal:n.signal})]);clearTimeout(r);let l=e,u;if(a.status==="fulfilled"&&a.value.ok&&(l=(await a.value.json()).version),i.status==="fulfilled"&&i.value.ok&&(u=(await i.value.json()).version),Oo({lastCheck:s,latestVersion:l,latestPluginVersion:u}),Ce(e,l)&&At(e,l),u){let y=xt();y&&Ce(y,u)&&Rt(y,u)}}catch{}}function At(e,t){console.log(O.default.yellow(`
55
55
  \u26A0\uFE0F Update available: badgerclaw ${O.default.dim(e)} \u2192 ${O.default.green(t)}`)+O.default.dim(`
56
56
  Run: `)+O.default.cyan("npm install -g badgerclaw")+`
57
- `)}function At(e,t){console.log(O.default.yellow(`
57
+ `)}function Rt(e,t){console.log(O.default.yellow(`
58
58
  \u26A0\uFE0F Plugin update available: @badgerclaw/connect ${O.default.dim(e)} \u2192 ${O.default.green(t)}`)+O.default.dim(`
59
59
  Run: `)+O.default.cyan("badgerclaw setup")+`
60
- `)}var Tt=c(require("os"));var Ie=c(require("fs")),K=c(require("path")),ie=c(require("os")),ce=require("child_process"),Pt="ai.badgerclaw.watch",Rt=K.default.join(ie.default.homedir(),"Library","LaunchAgents"),Ve=K.default.join(Rt,`${Pt}.plist`);function Eo(){try{return(0,ce.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function Do(){try{return(0,ce.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function No(e){let t=K.default.join(ie.default.homedir(),".badgerclaw"),o=Do(),s=K.default.dirname(o);return`<?xml version="1.0" encoding="UTF-8"?>
60
+ `)}var Ot=c(require("os"));var Ie=c(require("fs")),Y=c(require("path")),ie=c(require("os")),ce=require("child_process"),Pt="ai.badgerclaw.watch",Et=Y.default.join(ie.default.homedir(),"Library","LaunchAgents"),He=Y.default.join(Et,`${Pt}.plist`);function jo(){try{return(0,ce.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function Lo(){try{return(0,ce.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function Bo(e){let t=Y.default.join(ie.default.homedir(),".badgerclaw"),o=Lo(),s=Y.default.dirname(o);return`<?xml version="1.0" encoding="UTF-8"?>
61
61
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
62
62
  <plist version="1.0">
63
63
  <dict>
@@ -85,7 +85,7 @@ interact timeout 2 {
85
85
  <key>ThrottleInterval</key>
86
86
  <integer>30</integer>
87
87
  </dict>
88
- </plist>`}function Et(){if(ie.default.platform()==="darwin")try{let e=Eo();Ie.default.mkdirSync(Rt,{recursive:!0}),Ie.default.mkdirSync(K.default.join(ie.default.homedir(),".badgerclaw"),{recursive:!0}),Ie.default.writeFileSync(Ve,No(e));try{(0,ce.execSync)(`launchctl unload "${Ve}" 2>/dev/null`)}catch{}(0,ce.execSync)(`launchctl load "${Ve}"`),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 xe=c(require("fs")),le=c(require("path")),ke=c(require("os")),M=require("child_process"),He="badgerclaw-watch.service",Dt=le.default.join(ke.default.homedir(),".config","systemd","user"),To=le.default.join(Dt,He);function Oo(){try{return(0,M.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function jo(){try{return(0,M.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function Bo(e){let t=jo(),o=le.default.dirname(t);return`[Unit]
88
+ </plist>`}function Dt(){if(ie.default.platform()==="darwin")try{let e=jo();Ie.default.mkdirSync(Et,{recursive:!0}),Ie.default.mkdirSync(Y.default.join(ie.default.homedir(),".badgerclaw"),{recursive:!0}),Ie.default.writeFileSync(He,Bo(e));try{(0,ce.execSync)(`launchctl unload "${He}" 2>/dev/null`)}catch{}(0,ce.execSync)(`launchctl load "${He}"`),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 ke=c(require("fs")),le=c(require("path")),xe=c(require("os")),U=require("child_process"),Je="badgerclaw-watch.service",Nt=le.default.join(xe.default.homedir(),".config","systemd","user"),Uo=le.default.join(Nt,Je);function Mo(){try{return(0,U.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function Fo(){try{return(0,U.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function Go(e){let t=Fo(),o=le.default.dirname(t);return`[Unit]
89
89
  Description=BadgerClaw background watcher (heartbeat + pair events)
90
90
  After=network-online.target
91
91
  Wants=network-online.target
@@ -101,9 +101,9 @@ StandardError=append:%h/.badgerclaw/heartbeat.log
101
101
 
102
102
  [Install]
103
103
  WantedBy=default.target
104
- `}function Lo(){try{return(0,M.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function Nt(){if(ke.default.platform()==="linux"){if(!Lo()){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=Oo();xe.default.mkdirSync(Dt,{recursive:!0}),xe.default.mkdirSync(le.default.join(ke.default.homedir(),".badgerclaw"),{recursive:!0}),xe.default.writeFileSync(To,Bo(e)),(0,M.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,M.execSync)(`systemctl --user restart ${He}`,{stdio:"ignore"})}catch{}(0,M.execSync)(`systemctl --user enable --now ${He}`,{stdio:"ignore"});try{let t=(0,M.execSync)("whoami",{encoding:"utf-8"}).trim();(0,M.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 Ot(){let e=Tt.default.platform();if(e==="darwin")return Et();if(e==="linux")return Nt();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var Mo=2e3,Fo=12e4,Mt=new jt.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let{version:e}=W();ve(e);let t=gt(),o=pt(t),s=`${_t}/cli-auth?code=${o}`;console.log(q.default.yellow("Opening browser for authentication...")),console.log(q.default.dim(`If the browser doesn't open, visit: ${s}`)),await(0,Lt.default)(s);let n=(0,Bt.default)("Waiting for authentication...").start(),r=$t(),a=Date.now();for(;Date.now()-a<Fo;){try{let i=await r.post(`/api/v1/openclaw/cli/auth/poll/${o}`,{code_verifier:t,code_challenge:o});if(i.status===429){await new Promise(l=>setTimeout(l,5e3));continue}if(i.data?.access_token){let{access_token:l,user_id:m,expires_at:w,refresh_token:f,email:E}=i.data,D=Ut.default.createHash("sha256").update(`${X.default.hostname()}-${X.default.platform()}-${X.default.arch()}`).digest("hex").slice(0,16),N=`openclaw-${X.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${D}`;ye({access_token:l,user_id:m,instance_id:N,expires_at:w,refresh_token:f,email:E});try{let{version:T}=W();await r.post("/api/v1/openclaw/register",{instance_id:N,label:X.default.hostname(),version:T},{headers:{Authorization:`Bearer ${l}`}})}catch{}n.succeed(q.default.green(`Logged in as ${_e(m)}`));let S=await ne(!0);S>0&&(console.log(q.default.green(`\u2705 ${S} bot(s) automatically paired to OpenClaw.`)),console.log(q.default.yellow("Run: openclaw gateway restart to activate."))),Ot();return}}catch{}await new Promise(i=>setTimeout(i,Mo))}n.fail(q.default.red("Authentication timed out. Please try again.")),process.exit(1)});var Ft=require("commander"),qe=c(require("chalk"));var Gt=new Ft.Command("logout").description("Disconnect this machine and log out of BadgerClaw").action(async()=>{let e=h();if(!e){console.log(qe.default.yellow("Not logged in."));return}try{let t=Se(e.access_token),{version:o}=W();await t.post("/api/v1/openclaw/register",{instance_id:e.instance_id,label:require("os").hostname(),version:o,online:!1})}catch{}yt(),console.log(qe.default.green("Logged out \u2014 this machine is now disconnected."))});var Wt=require("commander"),Je=c(require("chalk"));var Vt=new Wt.Command("status").description("Show connected instance info").action(async()=>{let{version:e}=W();await ve(e);let t=h();(!t||!we())&&(console.log(Je.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(Je.default.green("Authenticated")),console.log(` User: ${_e(t.user_id)}`),console.log(` Instance: ${t.instance_id}`),console.log(` Expires: ${new Date(t.expires_at).toLocaleDateString()}`)});var de=require("commander"),k=c(require("chalk")),Ae=c(require("ora"));function ze(){we()||(console.log(k.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function Go(e){return/^[a-z0-9_]{4,20}$/.test(e)}function Wo(e){return e.replace(/_bot$/,"")}var Vo=new de.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").action(async e=>{ze(),Go(e)||(console.log(k.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let t=(0,Ae.default)(`Creating bot "${e}"...`).start();try{await C().post("/api/v1/openclaw/bots",{username:e}),t.succeed(k.default.green(`Bot "${e}" created successfully!`))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(k.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),Ho=new de.Command("list").description("List your bots").action(async()=>{ze();let e=(0,Ae.default)("Fetching bots...").start();try{let s=(await C().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),s.length===0){console.log(k.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(k.default.green(`Your bots (${s.length}):
105
- `));for(let n of s){let r=Wo(n.username||n.name),a=n.active!==!1?k.default.green("active"):k.default.dim("inactive");console.log(` ${k.default.bold(r)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(k.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),qo=new de.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{ze();let t=(0,Ae.default)(`Deactivating bot "${e}"...`).start();try{await C().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(k.default.green(`Bot "${e}" deactivated.`))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(k.default.red(`Failed to deactivate bot: ${s}`)),process.exit(1)}}),Ht=new de.Command("bot").description("Manage bots").addCommand(Vo).addCommand(Ho).addCommand(qo);var no=require("commander"),g=c(require("chalk"));var Ke=c(require("axios")),Jo=7331,qt=`http://localhost:${Jo}`,Ye="unknown";async function me(){try{let t=(await Ke.default.get(`${qt}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(Ye=t.pluginVersion),t}catch{return{status:"stopped",pid:null,lastRestart:null,pluginVersion:Ye,bots:[]}}}function Jt(e){e&&e!=="unknown"&&(Ye=e)}async function Q(){try{return{success:!0,message:(await Ke.default.post(`${qt}/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 Qt=require("commander"),d=c(require("chalk")),Zt=c(require("axios"));var B=c(require("os")),zt=c(require("crypto"));function ue(){let e=h();if(e?.instance_id)return e.instance_id;let t=zt.default.createHash("sha256").update(`${B.default.hostname()}-${B.default.platform()}-${B.default.arch()}`).digest("hex").slice(0,16);return`openclaw-${B.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function Pe(){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 $=require("child_process"),u=c(require("fs")),_=c(require("path")),ge=c(require("os")),I=c(require("axios"));async function G(e){return e.command_type==="update_cli"?Zo(e.payload?.target_version):e.command_type==="update_plugin"?es(e.payload?.target_version):e.command_type==="restart_gateway"?Qo():e.command_type==="leave_room"?gs(e.payload):e.command_type==="start_claude_code"?rs(e.payload):e.command_type==="stop_claude_code"?as(e.payload):e.command_type==="start_claude_control"?is(e.payload):e.command_type==="stop_claude_control"?cs(e.payload):e.command_type==="update_claude_tools"?ls(e.payload):e.command_type==="bot_share_notify"?ds(e.payload):e.command_type==="bot_share_revoked"?ms(e.payload):e.command_type==="bot_share_expired"?us(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function Qo(){try{return(0,$.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,$.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 Zo(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,$.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,$.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),n=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return os(),{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 es(e){let t=_.default.join(ge.default.homedir(),".openclaw","extensions","badgerclaw");if(!u.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,$.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";u.default.existsSync(n)&&(r=JSON.parse(u.default.readFileSync(n,"utf-8")).version||"unknown"),Jt(r),ts(s,t);let a=_.default.join(t,"package.json");if(u.default.existsSync(a)&&u.default.existsSync(n))try{let i=JSON.parse(u.default.readFileSync(a,"utf-8")),l=JSON.parse(u.default.readFileSync(n,"utf-8"));i.version=r,l.openclaw&&(i.openclaw={...i.openclaw,...l.openclaw}),u.default.writeFileSync(a,JSON.stringify(i,null,2)+`
106
- `)}catch{}try{(0,$.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}for(let i=0;i<15;i++){await new Promise(l=>setTimeout(l,1e3));try{let l=await I.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 ts(e,t){let o=_.default.join(e,"dist"),s=_.default.join(t,"dist");u.default.existsSync(o)&&(u.default.mkdirSync(s,{recursive:!0}),ct(o,s));let n=_.default.join(e,"openclaw.plugin.json");u.default.existsSync(n)&&u.default.copyFileSync(n,_.default.join(t,"openclaw.plugin.json"));let r=_.default.join(e,"scripts"),a=_.default.join(t,"scripts");u.default.existsSync(r)&&(u.default.mkdirSync(a,{recursive:!0}),ct(r,a));for(let i of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let l=_.default.join(t,i);u.default.existsSync(l)&&(u.default.statSync(l).isDirectory()?u.default.rmSync(l,{recursive:!0,force:!0}):u.default.unlinkSync(l))}}function ct(e,t){for(let o of u.default.readdirSync(e,{withFileTypes:!0})){let s=_.default.join(e,o.name),n=_.default.join(t,o.name);o.isDirectory()?(u.default.mkdirSync(n,{recursive:!0}),ct(s,n)):u.default.copyFileSync(s,n)}}function os(){try{try{(0,$.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,$.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,$.execSync)("sleep 1",{stdio:"pipe"});let e=(0,$.execSync)("which badgerclaw",{stdio:"pipe"}).toString().trim();(0,$.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,$.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function ss(){let e=_.default.join(ge.default.homedir(),".badgerclaw","workspace");u.default.mkdirSync(e,{recursive:!0});let t=_.default.join(e,".git");return u.default.existsSync(t)||(0,$.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),u.default.writeFileSync(_.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
104
+ `}function Vo(){try{return(0,U.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function Tt(){if(xe.default.platform()==="linux"){if(!Vo()){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=Mo();ke.default.mkdirSync(Nt,{recursive:!0}),ke.default.mkdirSync(le.default.join(xe.default.homedir(),".badgerclaw"),{recursive:!0}),ke.default.writeFileSync(Uo,Go(e)),(0,U.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,U.execSync)(`systemctl --user restart ${Je}`,{stdio:"ignore"})}catch{}(0,U.execSync)(`systemctl --user enable --now ${Je}`,{stdio:"ignore"});try{let t=(0,U.execSync)("whoami",{encoding:"utf-8"}).trim();(0,U.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 jt(){let e=Ot.default.platform();if(e==="darwin")return Dt();if(e==="linux")return Tt();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var Ho=2e3,Jo=12e4,Ft=new Lt.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let{version:e}=M();ve(e);let t=pt(),o=ft(t),s=`${bt}/cli-auth?code=${o}`;console.log(J.default.yellow("Opening browser for authentication...")),console.log(J.default.dim(`If the browser doesn't open, visit: ${s}`)),await(0,Ut.default)(s);let n=(0,Bt.default)("Waiting for authentication...").start(),r=St(),a=Date.now();for(;Date.now()-a<Jo;){try{let i=await r.post(`/api/v1/openclaw/cli/auth/poll/${o}`,{code_verifier:t,code_challenge:o});if(i.status===429){await new Promise(l=>setTimeout(l,5e3));continue}if(i.data?.access_token){let{access_token:l,user_id:u,expires_at:y,refresh_token:f,email:E}=i.data,D=Mt.default.createHash("sha256").update(`${X.default.hostname()}-${X.default.platform()}-${X.default.arch()}`).digest("hex").slice(0,16),N=`openclaw-${X.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${D}`;we({access_token:l,user_id:u,instance_id:N,expires_at:y,refresh_token:f,email:E});try{let{version:T}=M();await r.post("/api/v1/openclaw/register",{instance_id:N,label:X.default.hostname(),version:T},{headers:{Authorization:`Bearer ${l}`}})}catch{}n.succeed(J.default.green(`Logged in as ${_e(u)}`));let C=await ne(!0);C>0&&(console.log(J.default.green(`\u2705 ${C} bot(s) automatically paired to OpenClaw.`)),console.log(J.default.yellow("Run: openclaw gateway restart to activate."))),jt();return}}catch{}await new Promise(i=>setTimeout(i,Ho))}n.fail(J.default.red("Authentication timed out. Please try again.")),process.exit(1)});var Gt=require("commander"),qe=c(require("chalk"));var Vt=new Gt.Command("logout").description("Disconnect this machine and log out of BadgerClaw").action(async()=>{let e=h();if(!e){console.log(qe.default.yellow("Not logged in."));return}try{let t=Se(e.access_token),{version:o}=M();await t.post("/api/v1/openclaw/register",{instance_id:e.instance_id,label:require("os").hostname(),version:o,online:!1})}catch{}yt(),console.log(qe.default.green("Logged out \u2014 this machine is now disconnected."))});var Wt=require("commander"),ze=c(require("chalk"));var Ht=new Wt.Command("status").description("Show connected instance info").action(async()=>{let{version:e}=M();await ve(e);let t=h();(!t||!ye())&&(console.log(ze.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(ze.default.green("Authenticated")),console.log(` User: ${_e(t.user_id)}`),console.log(` Instance: ${t.instance_id}`),console.log(` Expires: ${new Date(t.expires_at).toLocaleDateString()}`)});var de=require("commander"),R=c(require("chalk")),Ae=c(require("ora"));function Ke(){ye()||(console.log(R.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function qo(e){return/^[a-z0-9_]{4,20}$/.test(e)}function zo(e){return e.replace(/_bot$/,"")}var Ko=new de.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").action(async e=>{Ke(),qo(e)||(console.log(R.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let t=(0,Ae.default)(`Creating bot "${e}"...`).start();try{await v().post("/api/v1/openclaw/bots",{username:e}),t.succeed(R.default.green(`Bot "${e}" created successfully!`))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(R.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),Yo=new de.Command("list").description("List your bots").action(async()=>{Ke();let e=(0,Ae.default)("Fetching bots...").start();try{let s=(await v().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),s.length===0){console.log(R.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(R.default.green(`Your bots (${s.length}):
105
+ `));for(let n of s){let r=zo(n.username||n.name),a=n.active!==!1?R.default.green("active"):R.default.dim("inactive");console.log(` ${R.default.bold(r)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(R.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),Xo=new de.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{Ke();let t=(0,Ae.default)(`Deactivating bot "${e}"...`).start();try{await v().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(R.default.green(`Bot "${e}" deactivated.`))}catch(o){let s=o.response?.data?.errors?.[0]||o.message;t.fail(R.default.red(`Failed to deactivate bot: ${s}`)),process.exit(1)}}),Jt=new de.Command("bot").description("Manage bots").addCommand(Ko).addCommand(Yo).addCommand(Xo);var ro=require("commander"),g=c(require("chalk"));var Xe=c(require("axios")),Qo=7331,qt=`http://localhost:${Qo}`,Ye="unknown";async function ue(){try{let t=(await Xe.default.get(`${qt}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(Ye=t.pluginVersion),t}catch{return{status:"stopped",pid:null,lastRestart:null,pluginVersion:Ye,bots:[]}}}function zt(e){e&&e!=="unknown"&&(Ye=e)}async function Q(){try{return{success:!0,message:(await Xe.default.post(`${qt}/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 Zt=require("commander"),d=c(require("chalk")),eo=c(require("axios"));var L=c(require("os")),Kt=c(require("crypto"));function me(){let e=h();if(e?.instance_id)return e.instance_id;let t=Kt.default.createHash("sha256").update(`${L.default.hostname()}-${L.default.platform()}-${L.default.arch()}`).digest("hex").slice(0,16);return`openclaw-${L.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function Re(){return{hostname:L.default.hostname(),os:L.default.platform(),arch:L.default.arch(),uptimeSeconds:Math.floor(L.default.uptime()),memFreeMb:Math.floor(L.default.freemem()/1024/1024)}}var S=require("child_process"),m=c(require("fs")),_=c(require("path")),ge=c(require("os")),k=c(require("axios"));async function G(e){return e.command_type==="update_cli"?ns(e.payload?.target_version):e.command_type==="update_plugin"?rs(e.payload?.target_version):e.command_type==="restart_gateway"?ss():e.command_type==="leave_room"?ys(e.payload):e.command_type==="start_claude_code"?ds(e.payload):e.command_type==="stop_claude_code"?us(e.payload):e.command_type==="start_claude_control"?ms(e.payload):e.command_type==="stop_claude_control"?gs(e.payload):e.command_type==="update_claude_tools"?ps(e.payload):e.command_type==="bot_share_notify"?fs(e.payload):e.command_type==="bot_share_revoked"?hs(e.payload):e.command_type==="bot_share_expired"?ws(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function ss(){try{return(0,S.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,S.execSync)("curl -s -X POST http://localhost:7331/restart",{stdio:"pipe",timeout:1e4}).toString()}`}}catch(e){return{success:!1,message:`Gateway restart failed: ${e.message||"unknown error"}`}}}}function ns(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,S.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,S.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),n=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return is(),{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 rs(e){let t=_.default.join(ge.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,S.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"),zt(r),as(s,t);let a=_.default.join(t,"package.json");if(m.default.existsSync(a)&&m.default.existsSync(n))try{let i=JSON.parse(m.default.readFileSync(a,"utf-8")),l=JSON.parse(m.default.readFileSync(n,"utf-8"));i.version=r,l.openclaw&&(i.openclaw={...i.openclaw,...l.openclaw}),m.default.writeFileSync(a,JSON.stringify(i,null,2)+`
106
+ `)}catch{}try{(0,S.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}for(let i=0;i<15;i++){await new Promise(l=>setTimeout(l,1e3));try{let l=await 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 as(e,t){let o=_.default.join(e,"dist"),s=_.default.join(t,"dist");m.default.existsSync(o)&&(m.default.mkdirSync(s,{recursive:!0}),lt(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}),lt(r,a));for(let i of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let l=_.default.join(t,i);m.default.existsSync(l)&&(m.default.statSync(l).isDirectory()?m.default.rmSync(l,{recursive:!0,force:!0}):m.default.unlinkSync(l))}}function lt(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}),lt(s,n)):m.default.copyFileSync(s,n)}}function is(){try{try{(0,S.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,S.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,S.execSync)("sleep 1",{stdio:"pipe"});let e=(0,S.execSync)("which badgerclaw",{stdio:"pipe"}).toString().trim();(0,S.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,S.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function cs(){let e=_.default.join(ge.default.homedir(),".badgerclaw","workspace");m.default.mkdirSync(e,{recursive:!0});let t=_.default.join(e,".git");return m.default.existsSync(t)||(0,S.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.
107
107
 
108
108
  When you receive a message, it will be formatted like:
109
109
  [Room: RoomName] Sender: message text
@@ -112,20 +112,21 @@ Reply using the reply tool with botId="..." and roomId="..."
112
112
  ALWAYS use the \`reply\` MCP tool to send your response back to the chat room.
113
113
  Use the exact botId and roomId provided in the message \u2014 do not modify them.
114
114
  Keep responses concise and helpful.
115
- `),e}var Ne=_.default.join(ge.default.homedir(),".badgerclaw","claude-code.lock");function ns(){try{u.default.mkdirSync(_.default.dirname(Ne),{recursive:!0});try{let e=u.default.statSync(Ne);if(Date.now()-e.mtimeMs<6e4)return!1;u.default.unlinkSync(Ne)}catch{}return u.default.writeFileSync(Ne,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function rs(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 pe(e.bot_id),{launchClaudeCode:o,recordSession:s,getActiveSessions:n,stopSession:r}=(De(),ut(it)),a=new Set;try{let E=(await I.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let D of E)if(D.botId!==t&&D.enabled!==!1){let N=D.port;typeof N=="number"&&N>=7332&&a.add(N)}}catch{}for(let f=7332;f<=7340;f++)try{(0,$.execSync)(`lsof -ti :${f} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(f)}catch{}let i=7332;for(;a.has(i);)i++;let l=n();for(let f of l)f.port===i&&(console.log(`[command-executor] Stopping existing session ${f.sessionId} on port ${i}`),r(f.sessionId));try{(0,$.execSync)(`lsof -ti :${i} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let m=e.session_id||`session-${Date.now()}`;await I.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:m,port:i},{timeout:1e4});let w=ss();return o({sessionId:m,port:i,projectDir:w}),s(m,0,0,i,w),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${m}, port: ${i})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function pe(e){if(e.startsWith("@"))return e;try{let o=(await I.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],s=_.default.join(ge.default.homedir(),".badgerclaw","bot-mapping.json");if(u.default.existsSync(s)){let n=JSON.parse(u.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 as(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await pe(e.bot_id),o=e.session_id;if(!o)try{let s=await I.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 I.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:s}=(De(),ut(it));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 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;o.startsWith("@")||(o=await pe(t));let s=e?.session_id||`cc-${Date.now()}`;return await I.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 cs(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;return o.startsWith("@")||(o=await pe(t)),await I.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 ls(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t||!e?.tools)return{success:!1,message:"Missing bot_id or tools in payload"};let o=t;return o.startsWith("@")||(o=await pe(t)),await I.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 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 I.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 ms(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 I.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 I.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 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 I.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 Kt=3e4,ps=15e4,eo="/api/v1/dashboard/heartbeat",fs="/api/v1/me/active-shares",Te=new Map,hs=3e4;function Oe(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 Te)s-r>hs&&Te.delete(n);return Te.has(o)?!0:(Te.set(o,s),!1)}function to(e,t){let o=Pe();return{instance_id:ue(),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}))}}async function x(){let{version:e}=W(),t=await me(),o=to(t,e);await C().post(eo,o)}function ys(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 Xt(){try{let o=(await C().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 Zt.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 oo=new Qt.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}=W();console.log(d.default.green(`Heartbeat daemon started (v${t})`)),console.log(d.default.dim(` Instance: ${ue()}`)),console.log(d.default.dim(` Interval: ${Kt/1e3}s`)),console.log(d.default.dim(` Press Ctrl+C to stop.
116
- `));let o=null,s=10,n=0,r=async()=>{try{await so();let a=await me(),i=to(a,t);ys(o,a)&&o!==null&&console.log(d.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let m=C(),w=await m.post(eo,i);n=0;let f=a.bots.length,E=a.bots.filter(S=>S.status==="running").length;console.log(d.default.dim(` [${new Date().toISOString()}] gateway=${a.status} bots=${E}/${f} running mem=${i.mem_free_mb}MB free`)),o=a;let D=w.data?.pending_commands||[],N=!1;for(let S of D)try{if(console.log(d.default.cyan(` [${new Date().toISOString()}] Received command: ${S.command_type} (${S.id})`)),await m.post(`/api/v1/dashboard/commands/${S.id}/ack`),Oe(S.command_type,S.payload?.bot_id)){console.log(d.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${S.command_type}`));continue}let T=await G(S);console.log(T.success?d.default.green(` [${new Date().toISOString()}] ${T.message}`):d.default.red(` [${new Date().toISOString()}] ${T.message}`)),await m.post(`/api/v1/dashboard/commands/${S.id}/result`,{status:T.success?"success":"failed",result:T.message,new_version:T.newVersion||null}),S.command_type==="update_cli"&&T.success&&(N=!0)}catch(T){console.log(d.default.dim(` [${new Date().toISOString()}] Command ${S.id} error: ${T.message}`))}if(N){console.log(d.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await x()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(a){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 Xt(),setInterval(r,Kt),setInterval(Xt,ps),_s(e.access_token,t),await new Promise(()=>{})});async function so(){let e=h();if(!e?.expires_at)return;let t=new Date(e.expires_at).getTime(),o=Date.now(),s=300*1e3;if(t-o<s){console.log(d.default.dim(` [${y()}] Token expires soon \u2014 refreshing proactively...`));let n=await Ue();console.log(n?d.default.green(` [${y()}] Token refreshed successfully`):d.default.yellow(` [${y()}] Token refresh failed \u2014 no refresh_token available`))}}var ws=2700*1e3;function _s(e,t){let o=3e3,s=3e4,n=null;async function r(){try{await so();let i=h()?.access_token||e,l=require("eventsource"),m=new l(`${U}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${i}`}});m.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`)),m.close(),r()},ws)},m.onmessage=async w=>{try{let f=JSON.parse(w.data);await bs(f)}catch{}},m.onerror=async()=>{m.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 se(e.pair_code,e.bot_name,e.bot_user_id,!0);try{let{execSync:t}=await import("child_process");t("openclaw gateway restart",{stdio:"ignore"}),console.log(d.default.green(` [${y()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await x()}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"),i=JSON.parse(s.readFileSync(a,"utf-8")),l=!1;if(i.channels?.badgerclaw?.accounts?.[o]&&(delete i.channels.badgerclaw.accounts[o],l=!0),i.agents?.list){let m=i.agents.list.length;i.agents.list=i.agents.list.filter(w=>w.id!==o),i.agents.list.length!==m&&(l=!0)}if(l){s.writeFileSync(a,JSON.stringify(i,null,2)),console.log(d.default.green(` [${y()}] Removed "${o}" from openclaw.json`));let{execSync:m}=await import("child_process");try{m("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 x()}catch{}}else if(e.type==="gateway-restart"){console.log(d.default.cyan(` [${y()}] Remote gateway-restart received`));let t=await Q();console.log(t.success?d.default.green(` [${y()}] Gateway restarted`):d.default.red(` [${y()}] Gateway restart failed: ${t.message}`));try{await x()}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}`)),Oe("start_claude_code",e.bot_id)){console.log(d.default.dim(` [${y()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await G({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 C().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await x()}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}`)),Oe("stop_claude_code",e.bot_id)){console.log(d.default.dim(` [${y()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await G({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 C().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await x()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(d.default.cyan(` [${y()}] Command: ${e.command_type} (${e.command_id})`)),Oe(e.command_type,e.payload?.bot_id)){console.log(d.default.dim(` [${y()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=C();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await G({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 x()}catch{}}}var ro=new no.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{let e=h();e||(console.log(g.default.yellow("Not logged in.")),process.exit(1)),await ne(!1),console.log(g.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=new t(`${U}/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(`
115
+ `),e}var Ne=_.default.join(ge.default.homedir(),".badgerclaw","claude-code.lock");function ls(){try{m.default.mkdirSync(_.default.dirname(Ne),{recursive:!0});try{let e=m.default.statSync(Ne);if(Date.now()-e.mtimeMs<6e4)return!1;m.default.unlinkSync(Ne)}catch{}return m.default.writeFileSync(Ne,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function ds(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!ls())return{success:!0,message:"Claude Code start already in progress, skipping duplicate"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await pe(e.bot_id),{launchClaudeCode:o,recordSession:s,getActiveSessions:n,stopSession:r}=(De(),gt(ct)),a=new Set;try{let E=(await k.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let D of E)if(D.botId!==t&&D.enabled!==!1){let N=D.port;typeof N=="number"&&N>=7332&&a.add(N)}}catch{}for(let f=7332;f<=7340;f++)try{(0,S.execSync)(`lsof -ti :${f} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(f)}catch{}let i=7332;for(;a.has(i);)i++;let l=n();for(let f of l)f.port===i&&(console.log(`[command-executor] Stopping existing session ${f.sessionId} on port ${i}`),r(f.sessionId));try{(0,S.execSync)(`lsof -ti :${i} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let u=e.session_id||`session-${Date.now()}`;await k.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:u,port:i},{timeout:1e4});let y=cs();return o({sessionId:u,port:i,projectDir:y}),s(u,0,0,i,y),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${u}, port: ${i})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function pe(e){if(e.startsWith("@"))return e;try{let o=(await k.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],s=_.default.join(ge.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 us(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await pe(e.bot_id),o=e.session_id;if(!o)try{let s=await 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}=(De(),gt(ct));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 ms(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;o.startsWith("@")||(o=await pe(t));let s=e?.session_id||`cc-${Date.now()}`;return await 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 gs(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;return o.startsWith("@")||(o=await pe(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 ps(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t||!e?.tools)return{success:!1,message:"Missing bot_id or tools in payload"};let o=t;return o.startsWith("@")||(o=await pe(t)),await 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 fs(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await 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 hs(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await 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 ws(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await 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 ys(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 Xt=3e4,_s=15e4,to="/api/v1/dashboard/heartbeat",bs="/api/v1/me/active-shares",Te=new Map,$s=3e4;function Oe(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 Te)s-r>$s&&Te.delete(n);return Te.has(o)?!0:(Te.set(o,s),!1)}function oo(e,t){let o=Re();return{instance_id:me(),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}))}}async function x(){let{version:e}=M(),t=await ue(),o=oo(t,e);await v().post(to,o)}function Ss(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 Qt(){try{let o=(await v().get(bs)).data?.shares||[],s={shares:o.map(n=>({botUserId:n.bot_user_id,sharedWithUserId:n.shared_with_user_id,expiresAt:n.expires_at||null,shareId:n.share_id}))};await eo.default.post("http://localhost:7331/bot-share/sync",s,{timeout:1e4}),console.log(d.default.dim(` [${w()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(d.default.dim(` [${w()}] Share sync failed (non-fatal): ${e.message}`))}}var so=new Zt.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}=M();console.log(d.default.green(`Heartbeat daemon started (v${t})`)),console.log(d.default.dim(` Instance: ${me()}`)),console.log(d.default.dim(` Interval: ${Xt/1e3}s`)),console.log(d.default.dim(` Press Ctrl+C to stop.
116
+ `));let o=null,s=10,n=0,r=async()=>{try{await no();let a=await ue(),i=oo(a,t);Ss(o,a)&&o!==null&&console.log(d.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let u=v(),y=await u.post(to,i);n=0;let f=a.bots.length,E=a.bots.filter(C=>C.status==="running").length;console.log(d.default.dim(` [${new Date().toISOString()}] gateway=${a.status} bots=${E}/${f} running mem=${i.mem_free_mb}MB free`)),o=a;let D=y.data?.pending_commands||[],N=!1;for(let C of D)try{if(console.log(d.default.cyan(` [${new Date().toISOString()}] Received command: ${C.command_type} (${C.id})`)),await u.post(`/api/v1/dashboard/commands/${C.id}/ack`),Oe(C.command_type,C.payload?.bot_id)){console.log(d.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${C.command_type}`));continue}let T=await G(C);console.log(T.success?d.default.green(` [${new Date().toISOString()}] ${T.message}`):d.default.red(` [${new Date().toISOString()}] ${T.message}`)),await u.post(`/api/v1/dashboard/commands/${C.id}/result`,{status:T.success?"success":"failed",result:T.message,new_version:T.newVersion||null}),C.command_type==="update_cli"&&T.success&&(N=!0)}catch(T){console.log(d.default.dim(` [${new Date().toISOString()}] Command ${C.id} error: ${T.message}`))}if(N){console.log(d.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await x()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(a){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 Qt(),setInterval(r,Xt),setInterval(Qt,_s),vs(e.access_token,t),await new Promise(()=>{})});async function no(){let e=h();if(!e?.expires_at)return;let t=new Date(e.expires_at).getTime(),o=Date.now(),s=300*1e3;if(t-o<s){console.log(d.default.dim(` [${w()}] Token expires soon \u2014 refreshing proactively...`));let n=await Me();console.log(n?d.default.green(` [${w()}] Token refreshed successfully`):d.default.yellow(` [${w()}] Token refresh failed \u2014 no refresh_token available`))}}var Cs=2700*1e3;function vs(e,t){let o=3e3,s=3e4,n=null;async function r(){try{await no();let i=h()?.access_token||e,l=require("eventsource"),u=new l(`${A}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${i}`}});u.onopen=()=>{o=3e3,console.log(d.default.dim(` [${w()}] SSE connected \u2014 listening for real-time events`)),n&&clearTimeout(n),n=setTimeout(()=>{console.log(d.default.dim(` [${w()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),u.close(),r()},Cs)},u.onmessage=async y=>{try{let f=JSON.parse(y.data);await Is(f)}catch{}},u.onerror=async()=>{u.close(),n&&(clearTimeout(n),n=null),console.log(d.default.dim(` [${w()}] SSE disconnected \u2014 reconnecting in ${o/1e3}s...`)),setTimeout(r,o),o=Math.min(o*1.5,s)}}catch(a){console.log(d.default.dim(` [${w()}] SSE connection failed: ${a.message}`)),setTimeout(r,o),o=Math.min(o*1.5,s)}}r()}function w(){return new Date().toISOString()}async function Is(e){if(e.type==="pair"){console.log(d.default.cyan(` [${w()}] Pair event: ${e.bot_name}`)),await se(e.pair_code,e.bot_name,e.bot_user_id,!0);try{let{execSync:t}=await import("child_process");t("openclaw gateway restart",{stdio:"ignore"}),console.log(d.default.green(` [${w()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await x()}catch{}}else if(e.type==="bot.delete"&&e.bot_user_id){let t=e.bot_user_id,o=t.split(":")[0].replace("@","").replace(/_bot$/,"");console.log(d.default.yellow(` [${w()}] Bot deleted: ${t}`));try{let s=await import("fs"),n=await import("path"),r=await import("os"),a=n.join(r.homedir(),".openclaw","openclaw.json"),i=JSON.parse(s.readFileSync(a,"utf-8")),l=!1;if(i.channels?.badgerclaw?.accounts?.[o]&&(delete i.channels.badgerclaw.accounts[o],l=!0),i.agents?.list){let u=i.agents.list.length;i.agents.list=i.agents.list.filter(y=>y.id!==o),i.agents.list.length!==u&&(l=!0)}if(l){s.writeFileSync(a,JSON.stringify(i,null,2)),console.log(d.default.green(` [${w()}] Removed "${o}" from openclaw.json`));let{execSync:u}=await import("child_process");try{u("openclaw gateway restart",{stdio:"ignore"}),console.log(d.default.green(` [${w()}] Gateway restarted`))}catch{}}}catch(s){console.log(d.default.red(` [${w()}] Failed to clean up bot: ${s}`))}try{await x()}catch{}}else if(e.type==="gateway-restart"){console.log(d.default.cyan(` [${w()}] Remote gateway-restart received`));let t=await Q();console.log(t.success?d.default.green(` [${w()}] Gateway restarted`):d.default.red(` [${w()}] Gateway restart failed: ${t.message}`));try{await x()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(d.default.cyan(` [${w()}] Claude Code START: bot=${e.bot_id}`)),Oe("start_claude_code",e.bot_id)){console.log(d.default.dim(` [${w()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await G({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 v().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await x()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(d.default.cyan(` [${w()}] Claude Code STOP: bot=${e.bot_id}`)),Oe("stop_claude_code",e.bot_id)){console.log(d.default.dim(` [${w()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await G({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 v().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await x()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(d.default.cyan(` [${w()}] Command: ${e.command_type} (${e.command_id})`)),Oe(e.command_type,e.payload?.bot_id)){console.log(d.default.dim(` [${w()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=v();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await G({id:e.command_id,command_type:e.command_type,payload:e.payload});await t.post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:o.success?"success":"failed",result:o.message,new_version:o.newVersion||null}),e.command_type==="update_cli"&&o.success&&(console.log(d.default.cyan(` [${w()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await x()}catch{}}}var ao=new ro.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{let e=h();e||(console.log(g.default.yellow("Not logged in.")),process.exit(1)),await ne(!1),console.log(g.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=new t(`${A}/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(`
117
117
  \u{1F4F1} Pair event received: ${n.bot_name}`)),await se(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(`
118
118
  \u{1F504} Remote gateway-restart command received`));let r=await Q();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 x(),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.bot_user_id){let r=n.bot_user_id,a=r.split(":")[0].replace("@","").replace(/_bot$/,"");console.log(g.default.yellow(`
119
- \u{1F5D1}\uFE0F Bot deleted: ${r} \u2014 removing from OpenClaw config...`));try{let i=await import("fs"),l=await import("path"),m=await import("os"),w=l.join(m.homedir(),".openclaw","openclaw.json"),f=JSON.parse(i.readFileSync(w,"utf-8")),E=!1;if(f.channels?.badgerclaw?.accounts?.[a]&&(delete f.channels.badgerclaw.accounts[a],E=!0),f.agents?.list){let D=f.agents.list.length;f.agents.list=f.agents.list.filter(N=>N.id!==a),f.agents.list.length!==D&&(E=!0)}if(E){i.writeFileSync(w,JSON.stringify(f,null,2)),console.log(g.default.green(` \u2705 Removed "${a}" from openclaw.json`));let{execSync:D}=await import("child_process");try{D("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(" \u2705 Gateway restarted"))}catch{console.log(g.default.dim(" Gateway restart failed \u2014 restart manually"))}}else console.log(g.default.dim(` "${a}" not found in openclaw.json \u2014 nothing to remove`))}catch(i){console.log(g.default.red(` Failed to update openclaw.json: ${i}`))}}else if(n.type==="claude_code.start"&&n.bot_id&&n.room_id){console.log(g.default.cyan(`
120
- \u{1F916} Claude Code START received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await G({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 C().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await x()}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(`
121
- \u{1F916} Claude Code STOP received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await G({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 C().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await x()}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(`
122
- \u26A1 SSE command received: ${n.command_type} (${n.command_id})`));try{let r=C();await r.post(`/api/v1/dashboard/commands/${n.command_id}/ack`);let a=await G({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 x()}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 ao=require("commander"),A=c(require("chalk")),lt=require("child_process"),L=c(require("fs")),io=c(require("os")),co=c(require("path")),Z=co.default.join(io.default.homedir(),".openclaw","openclaw.json"),fe=Z+".badgerclaw-stash";function $s(){if(!L.default.existsSync(Z))return null;try{let e=JSON.parse(L.default.readFileSync(Z,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,L.default.writeFileSync(Z,JSON.stringify(e,null,2)),L.default.writeFileSync(fe,JSON.stringify(t,null,2)),t):null}catch{return null}}function Ss(){if(L.default.existsSync(fe))try{let e=JSON.parse(L.default.readFileSync(fe,"utf-8")),t=JSON.parse(L.default.readFileSync(Z,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,L.default.writeFileSync(Z,JSON.stringify(t,null,2)),L.default.unlinkSync(fe)}catch(e){console.log(A.default.yellow(` \u26A0\uFE0F Could not restore config: ${e.message}`)),console.log(A.default.yellow(` Your bot credentials are backed up at: ${fe}`))}}var lo=new ao.Command("setup").description("Install or update the OpenClaw BadgerClaw plugin safely (handles config automatically)").action(async()=>{console.log(A.default.green(`
119
+ \u{1F5D1}\uFE0F Bot deleted: ${r} \u2014 removing from OpenClaw config...`));try{let i=await import("fs"),l=await import("path"),u=await import("os"),y=l.join(u.homedir(),".openclaw","openclaw.json"),f=JSON.parse(i.readFileSync(y,"utf-8")),E=!1;if(f.channels?.badgerclaw?.accounts?.[a]&&(delete f.channels.badgerclaw.accounts[a],E=!0),f.agents?.list){let D=f.agents.list.length;f.agents.list=f.agents.list.filter(N=>N.id!==a),f.agents.list.length!==D&&(E=!0)}if(E){i.writeFileSync(y,JSON.stringify(f,null,2)),console.log(g.default.green(` \u2705 Removed "${a}" from openclaw.json`));let{execSync:D}=await import("child_process");try{D("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(" \u2705 Gateway restarted"))}catch{console.log(g.default.dim(" Gateway restart failed \u2014 restart manually"))}}else console.log(g.default.dim(` "${a}" not found in openclaw.json \u2014 nothing to remove`))}catch(i){console.log(g.default.red(` Failed to update openclaw.json: ${i}`))}}else if(n.type==="claude_code.start"&&n.bot_id&&n.room_id){console.log(g.default.cyan(`
120
+ \u{1F916} Claude Code START received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await G({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 v().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await x()}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(`
121
+ \u{1F916} Claude Code STOP received: bot=${n.bot_id} room=${n.room_id}`));try{let r=await G({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 v().post(`/api/v1/dashboard/commands/${n.command_id}/result`,{status:r.success?"success":"failed",result:r.message})}catch{}try{await x()}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(`
122
+ \u26A1 SSE command received: ${n.command_type} (${n.command_id})`));try{let r=v();await r.post(`/api/v1/dashboard/commands/${n.command_id}/ack`);let a=await G({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 x()}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 mo=require("commander"),$=c(require("chalk")),je=require("child_process"),B=c(require("fs")),go=c(require("os")),po=c(require("path"));var io=c(require("fs")),co=c(require("os")),lo=c(require("path")),V=c(require("chalk"));var ks=`${A}/api/v1/dashboard/versions/latest`,xs=2500,As=new Set(["setup","logout","help","--version","-V","--help","-h"]),Rs=lo.default.join(co.default.homedir(),".openclaw/extensions/badgerclaw/node_modules/@badgerclaw/connect/package.json");function dt(){return"0.2.19"}function Ps(){try{let e=io.default.readFileSync(Rs,"utf-8");return JSON.parse(e).version??null}catch{return null}}async function Es(){let e=new AbortController,t=setTimeout(()=>e.abort(),xs);try{let o=await fetch(ks,{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 Ds(e){let t=[];if(e.cli&&e.cli!=="unknown"){let o=dt();o!==e.cli&&t.push({component:"cli",current:o,approved:e.cli})}if(e.plugin&&e.plugin!=="unknown"){let o=Ps();(o===null||o!==e.plugin)&&t.push({component:"plugin",current:o??"not installed",approved:e.plugin})}return t}function Ns(e){return e[2]}function Ts(e){return!e||e.startsWith("-")?!0:As.has(e)}function Os(e){let t=[];t.push(""),t.push(V.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let s=o.component.padEnd(7);t.push(` ${s} ${V.default.yellow(o.current)} \u2192 ${V.default.green(o.approved)} ${V.default.dim("(admin-approved)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the admin-approved versions."),t.push(""),t.push(V.default.green(" To fix, run:")),t.push(V.default.green.bold(" badgerclaw setup")),t.push(""),t.push(V.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
123
+ `)}async function uo(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=Ns(e);if(Ts(t))return;let o=await Es();if(!o)return;let s=Ds(o);s.length!==0&&(process.stderr.write(Os(s)),process.exit(1))}var Z=po.default.join(go.default.homedir(),".openclaw","openclaw.json"),fe=Z+".badgerclaw-stash";async function js(){try{let e=await fetch(`${A}/api/v1/dashboard/versions/latest`,{headers:{Accept:"application/json"}});if(!e.ok)return{cli:null,plugin: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)}}catch{return{cli:null,plugin:null}}}function Ls(){if(!B.default.existsSync(Z))return null;try{let e=JSON.parse(B.default.readFileSync(Z,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,B.default.writeFileSync(Z,JSON.stringify(e,null,2)),B.default.writeFileSync(fe,JSON.stringify(t,null,2)),t):null}catch{return null}}function Bs(){if(B.default.existsSync(fe))try{let e=JSON.parse(B.default.readFileSync(fe,"utf-8")),t=JSON.parse(B.default.readFileSync(Z,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,B.default.writeFileSync(Z,JSON.stringify(t,null,2)),B.default.unlinkSync(fe)}catch(e){console.log($.default.yellow(` \u26A0\uFE0F Could not restore config: ${e.message}`)),console.log($.default.yellow(` Your bot credentials are backed up at: ${fe}`))}}var fo=new mo.Command("setup").description("Install or update the OpenClaw BadgerClaw plugin safely (handles config automatically)").action(async()=>{console.log($.default.green(`
123
124
  \u{1F9A1} BadgerClaw Setup
124
- `));let e=$s();e&&console.log(A.default.dim(" Existing bot config stashed temporarily...")),console.log(A.default.dim(" Installing @badgerclaw/connect plugin..."));let t=(0,lt.spawnSync)("openclaw",["plugins","install","@badgerclaw/connect","--dangerously-force-unsafe-install"],{stdio:"inherit",shell:!0});e&&(Ss(),console.log(A.default.dim(" Bot config restored."))),t.status!==0&&(console.log(A.default.red(`
125
- \u274C Plugin install failed. Your bot config has been restored.`)),process.exit(1)),console.log(A.default.green(`
126
- \u2705 BadgerClaw plugin installed successfully!`)),console.log(A.default.dim(`
127
- Restarting OpenClaw gateway to load plugin...`)),(0,lt.spawnSync)("openclaw",["gateway","restart"],{stdio:"inherit",shell:!0}).status===0?console.log(A.default.green(" Gateway restarted.")):console.log(A.default.yellow(" Gateway restart failed or not running \u2014 start it manually: openclaw gateway start")),console.log(A.default.dim("\nNext: run `badgerclaw login` to authenticate."))});var uo=require("commander"),b=c(require("chalk"));var go=new uo.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{h()||(console.log(b.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=W(),o=Pe(),s=await me();console.log(b.default.bold.green(`
125
+ `));let e=await js();if(e.cli){let r=dt();r!==e.cli?(console.log($.default.dim(` Updating CLI: ${r} \u2192 ${e.cli} (admin-approved)...`)),(0,je.spawnSync)("npm",["install","-g",`badgerclaw@${e.cli}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log($.default.red("\n\u274C CLI update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log($.default.green(` \u2705 CLI updated to ${e.cli}`))):console.log($.default.dim(` CLI already at approved version ${r}.`))}let t=Ls();t&&console.log($.default.dim(" Existing bot config stashed temporarily..."));let o=e.plugin?`@badgerclaw/connect@${e.plugin}`:"@badgerclaw/connect";e.plugin?console.log($.default.dim(` Installing ${o} (admin-approved)...`)):console.log($.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let s=(0,je.spawnSync)("openclaw",["plugins","install",o,"--dangerously-force-unsafe-install"],{stdio:"inherit",shell:!0});t&&(Bs(),console.log($.default.dim(" Bot config restored."))),s.status!==0&&(console.log($.default.red(`
126
+ \u274C Plugin install failed. Your bot config has been restored.`)),process.exit(1)),console.log($.default.green(`
127
+ \u2705 BadgerClaw plugin installed successfully!`)),console.log($.default.dim(`
128
+ Restarting OpenClaw gateway to load plugin...`)),(0,je.spawnSync)("openclaw",["gateway","restart"],{stdio:"inherit",shell:!0}).status===0?console.log($.default.green(" Gateway restarted.")):console.log($.default.yellow(" Gateway restart failed or not running \u2014 start it manually: openclaw gateway start")),console.log($.default.dim("\nNext: run `badgerclaw login` to authenticate."))});var wo=require("commander"),b=c(require("chalk"));var yo=new wo.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{h()||(console.log(b.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=M(),o=Re(),s=await ue();console.log(b.default.bold.green(`
128
129
  BadgerClaw Dashboard
129
- `)),console.log(b.default.bold(" Instance")),console.log(` ID: ${ue()}`),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: ${mo(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: ${mo(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 i of r.roomDetails)console.log(b.default.dim(` ${i.roomName} \u2014 ${i.messagesInRoom} msgs, last: ${i.lastActivityInRoom??"N/A"}`))}console.log()}}console.log(b.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function mo(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 dt=require("commander"),ee=c(require("chalk")),po=c(require("ora"));var Cs=new dt.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{h()||(console.log(ee.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,po.default)("Restarting gateway...").start(),o=await Q();if(o.success){t.succeed(ee.default.green(`Gateway restarted: ${o.message}`));try{await x(),console.log(ee.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(ee.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(ee.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),fo=new dt.Command("gateway").description("Manage the OpenClaw gateway").addCommand(Cs);var H=require("commander"),p=c(require("chalk")),Y=c(require("ora")),V=c(require("axios"));De();var z="http://localhost:7331",vs=new H.Command("start").description("Start a Claude Code session for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID (default: auto-generated)").option("--port <port>","MCP server port (default: 7332)","7332").option("--project <dir>","Project directory",process.cwd()).action(async e=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=e.sessionId||`session-${Date.now()}`,s=parseInt(e.port,10),n=e.project.replace(/^~/,process.env.HOME||""),r=(0,Y.default)("Starting Claude Code session...").start();try{await V.default.post(`${z}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),r.text="Gateway toggled \u2014 launching MCP server...";let i=ot({sessionId:o,port:s,projectDir:n}).pid||0;await new Promise(l=>setTimeout(l,1500)),r.text="MCP server running \u2014 launching Claude Code...",st({sessionId:o,port:s,projectDir:n}),nt(o,0,i,s,n),r.succeed(p.default.green("Claude Code session started")+p.default.dim(` (session: ${o}, port: ${s})`)),console.log(p.default.dim(` Bot: ${e.bot}`)),console.log(p.default.dim(` Room: ${e.room}`)),console.log(p.default.dim(` Project: ${n}`)),console.log(p.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let i=a.response?.data?.message||a.message||"Unknown error";r.fail(p.default.red(`Failed to start Claude Code: ${i}`)),process.exit(1)}}),Is=new H.Command("stop").description("Stop a Claude Code session").option("--bot <botId>","Bot ID or username").option("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID to stop").action(async e=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,Y.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await V.default.post(`${z}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let s=e.sessionId;if(!s)try{let a=((await V.default.get(`${z}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(i=>i.botId===e.bot&&i.roomId===e.room);a&&(s=a.sessionId)}catch{}s?(rt(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)}}),xs=new H.Command("status").description("Show active Claude Code sessions").action(async()=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,Y.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await V.default.get(`${z}/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(`
130
+ `)),console.log(b.default.bold(" Instance")),console.log(` ID: ${me()}`),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: ${ho(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: ${ho(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 i of r.roomDetails)console.log(b.default.dim(` ${i.roomName} \u2014 ${i.messagesInRoom} msgs, last: ${i.lastActivityInRoom??"N/A"}`))}console.log()}}console.log(b.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function ho(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 ut=require("commander"),ee=c(require("chalk")),_o=c(require("ora"));var Us=new ut.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{h()||(console.log(ee.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,_o.default)("Restarting gateway...").start(),o=await Q();if(o.success){t.succeed(ee.default.green(`Gateway restarted: ${o.message}`));try{await x(),console.log(ee.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(ee.default.dim(" Could not push heartbeat \u2014 daemon may not be running."))}}else t.fail(ee.default.red(`Gateway restart failed: ${o.message}`)),process.exit(1)}),bo=new ut.Command("gateway").description("Manage the OpenClaw gateway").addCommand(Us);var H=require("commander"),p=c(require("chalk")),K=c(require("ora")),W=c(require("axios"));De();var z="http://localhost:7331",Ms=new H.Command("start").description("Start a Claude Code session for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID (default: auto-generated)").option("--port <port>","MCP server port (default: 7332)","7332").option("--project <dir>","Project directory",process.cwd()).action(async e=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=e.sessionId||`session-${Date.now()}`,s=parseInt(e.port,10),n=e.project.replace(/^~/,process.env.HOME||""),r=(0,K.default)("Starting Claude Code session...").start();try{await W.default.post(`${z}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),r.text="Gateway toggled \u2014 launching MCP server...";let i=st({sessionId:o,port:s,projectDir:n}).pid||0;await new Promise(l=>setTimeout(l,1500)),r.text="MCP server running \u2014 launching Claude Code...",nt({sessionId:o,port:s,projectDir:n}),rt(o,0,i,s,n),r.succeed(p.default.green("Claude Code session started")+p.default.dim(` (session: ${o}, port: ${s})`)),console.log(p.default.dim(` Bot: ${e.bot}`)),console.log(p.default.dim(` Room: ${e.room}`)),console.log(p.default.dim(` Project: ${n}`)),console.log(p.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let i=a.response?.data?.message||a.message||"Unknown error";r.fail(p.default.red(`Failed to start Claude Code: ${i}`)),process.exit(1)}}),Fs=new H.Command("stop").description("Stop a Claude Code session").option("--bot <botId>","Bot ID or username").option("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID to stop").action(async e=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,K.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await W.default.post(`${z}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let s=e.sessionId;if(!s)try{let a=((await W.default.get(`${z}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(i=>i.botId===e.bot&&i.roomId===e.room);a&&(s=a.sessionId)}catch{}s?(at(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)}}),Gs=new H.Command("status").description("Show active Claude Code sessions").action(async()=>{h()||(console.log(p.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,K.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await W.default.get(`${z}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let s=it();if(t.stop(),o.length===0&&s.length===0){console.log(p.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(p.default.bold(`
130
131
  Gateway Claude Code Rooms:`)),console.log(p.default.dim(" Bot".padEnd(30)+"Room".padEnd(30)+"Session".padEnd(20)+"Enabled")),console.log(p.default.dim(" "+"-".repeat(88)));for(let n of o){let r=n.enabled?p.default.green("ON"):p.default.dim("OFF");console.log(` ${(n.botId||"").padEnd(30)}${(n.roomName||n.roomId||"").padEnd(30)}${(n.sessionId||"-").padEnd(20)}${r}`)}}if(s.length>0){console.log(p.default.bold(`
131
- Local Sessions:`)),console.log(p.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(p.default.dim(" "+"-".repeat(90)));for(let n of s)console.log(` ${n.sessionId.padEnd(25)}${String(n.port).padEnd(8)}${String(n.mcpPid).padEnd(10)}${n.projectDir.padEnd(40)}${n.startedAt}`)}console.log("")}catch(o){t.fail(p.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),ks=new H.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,Y.default)("Grouping bot+room into session...").start();try{await V.default.post(`${z}/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)}}),As=new H.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,Y.default)("Adding user to allowlist...").start();try{await V.default.post(`${z}/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)}}),Ps=new H.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,Y.default)("Removing user from allowlist...").start();try{await V.default.post(`${z}/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)}}),ho=new H.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(vs).addCommand(Is).addCommand(xs).addCommand(ks).addCommand(As).addCommand(Ps);var P=new yo.Command;P.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.18");P.addCommand(Mt);P.addCommand(Gt);P.addCommand(Vt);P.addCommand(Ht);P.addCommand(It);P.addCommand(ro);P.addCommand(lo);P.addCommand(oo);P.addCommand(go);P.addCommand(fo);P.addCommand(ho);P.parse(process.argv);
132
+ 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)}}),Vs=new H.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,K.default)("Grouping bot+room into session...").start();try{await W.default.post(`${z}/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)}}),Ws=new H.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,K.default)("Adding user to allowlist...").start();try{await W.default.post(`${z}/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)}}),Hs=new H.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,K.default)("Removing user from allowlist...").start();try{await W.default.post(`${z}/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)}}),$o=new H.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(Ms).addCommand(Fs).addCommand(Gs).addCommand(Vs).addCommand(Ws).addCommand(Hs);async function Js(){await uo(process.argv);let e=new So.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.19"),e.addCommand(Ft),e.addCommand(Vt),e.addCommand(Ht),e.addCommand(Jt),e.addCommand(kt),e.addCommand(ao),e.addCommand(fo),e.addCommand(so),e.addCommand(yo),e.addCommand(bo),e.addCommand($o),e.parse(process.argv)}Js().catch(e=>{console.error(e),process.exit(1)});
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "badgerclaw",
3
- "version": "0.2.18",
4
- "description": "BadgerClaw CLI \u2014 one-click bot provisioning",
3
+ "version": "0.2.19",
4
+ "description": "BadgerClaw CLI one-click bot provisioning",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "badgerclaw": "./dist/index.js"
@@ -32,4 +32,4 @@
32
32
  "esbuild": "^0.28.0",
33
33
  "typescript": "^5.3.0"
34
34
  }
35
- }
35
+ }