badgerclaw 0.2.58 → 0.2.59

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.
@@ -35,17 +35,39 @@ USER root
35
35
  # lazy_deps.py uses (tools/lazy_deps.py:126 in the upstream image as of
36
36
  # 2026-05-15), so behaviour matches what a healthy lazy-install would
37
37
  # produce — just without the startup-order race.
38
+ #
39
+ # build-essential + cmake: as of the 2026-06-07 upstream rebuild
40
+ # (Debian 13 / Python 3.13.5) the image ships only gcc/cc — no
41
+ # cmake/make/g++. mautrix[encryption] pulls python-olm, which compiles
42
+ # libolm from source and needs all three, so the install dies with
43
+ # `FileNotFoundError: 'cmake'`. We add the toolchain, then purge it in
44
+ # the same layer so the shipped image stays slim. Verified on a clean
45
+ # host build 2026-06-07.
46
+ #
47
+ # aiohttp-socks + Markdown: upstream's gateway/platforms/matrix.py now
48
+ # imports both at adapter-load time. They're not in the lazy_deps set we
49
+ # mirror above, so without them the adapter silently fails with
50
+ # "Matrix: required packages not installed (aiohttp-socks==0.11.0)" and
51
+ # the bot connects to zero platforms.
52
+ #
38
53
  # `uv` is at /usr/local/bin/uv in the upstream image, not inside the
39
54
  # venv. Targeting the venv via --python keeps the install scoped to the
40
55
  # same interpreter that hermes runs under.
41
- RUN /usr/local/bin/uv pip install \
56
+ RUN apt-get update \
57
+ && apt-get install -y --no-install-recommends build-essential cmake \
58
+ && /usr/local/bin/uv pip install \
42
59
  --python /opt/hermes/.venv/bin/python \
43
60
  --no-cache \
44
61
  "mautrix[encryption]==0.21.0" \
45
62
  "asyncpg>=0.29,<1" \
46
63
  "aiosqlite>=0.19,<1" \
64
+ "aiohttp-socks==0.11.0" \
65
+ "Markdown" \
47
66
  && /opt/hermes/.venv/bin/python -c \
48
- "from mautrix.types import EventType; from mautrix.crypto.store.asyncpg import PgCryptoStore; print('mautrix+asyncpg import OK')"
67
+ "from mautrix.types import EventType; from mautrix.crypto.store.asyncpg import PgCryptoStore; import aiohttp_socks, markdown; print('mautrix+asyncpg+socks+markdown import OK')" \
68
+ && apt-get purge -y build-essential cmake \
69
+ && apt-get autoremove -y \
70
+ && rm -rf /var/lib/apt/lists/*
49
71
 
50
72
  # Don't override ENTRYPOINT/CMD — the upstream values (`tini` calling
51
73
  # /opt/hermes/docker/entrypoint.sh) handle UID remap, volume chown, and
package/dist/index.js CHANGED
@@ -1,20 +1,20 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Sr=Object.create;var tt=Object.defineProperty;var $r=Object.getOwnPropertyDescriptor;var vr=Object.getOwnPropertyNames;var Cr=Object.getPrototypeOf,Ir=Object.prototype.hasOwnProperty;var L=(e,t)=>()=>(e&&(t=e(e=0)),t);var kr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Nt=(e,t)=>{for(var o in t)tt(e,o,{get:t[o],enumerable:!0})},Eo=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of vr(t))!Ir.call(e,r)&&r!==o&&tt(e,r,{get:()=>t[r],enumerable:!(n=$r(t,r))||n.enumerable});return e};var d=(e,t,o)=>(o=e!=null?Sr(Cr(e)):{},Eo(t||!e||!e.__esModule?tt(o,"default",{value:e,enumerable:!0}):o,e)),Po=e=>Eo(tt({},"__esModule",{value:!0}),e);function S(){try{let e=Oe.default.readFileSync(Mt,"utf-8");return JSON.parse(e)}catch{return null}}function ot(e){Oe.default.mkdirSync(Lo,{recursive:!0}),Oe.default.writeFileSync(Mt,JSON.stringify(e,null,2),{mode:384})}function De(){try{Oe.default.unlinkSync(Mt)}catch{}}function nt(){let e=S();return e?new Date(e.expires_at)>new Date:!1}function rt(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var Oe,Bt,To,Lo,Mt,N=L(()=>{"use strict";Oe=d(require("fs")),Bt=d(require("path")),To=d(require("os")),Lo=Bt.default.join(To.default.homedir(),".badgerclaw"),Mt=Bt.default.join(Lo,"auth.json")});function Ut(){return No.default.createHash("sha256").update(`${W.default.hostname()}-${W.default.platform()}-${W.default.arch()}`).digest("hex").slice(0,16)}function K(){let e=S();if(e?.instance_id)return e.instance_id;let t=Ut();return`openclaw-${W.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function st(){return{hostname:W.default.hostname(),os:W.default.platform(),arch:W.default.arch(),uptimeSeconds:Math.floor(W.default.uptime()),memFreeMb:Math.floor(W.default.freemem()/1024/1024)}}var W,No,$e=L(()=>{"use strict";W=d(require("os")),No=d(require("crypto"));N()});var jo,j,Bo,ne=L(()=>{"use strict";jo=process.env.BADGERCLAW_ENV==="local",j=process.env.BADGERCLAW_API_URL??(jo?"http://localhost:8000":"https://api.badger.signout.io"),Bo=process.env.BADGERCLAW_AUTH_URL??(jo?"http://localhost:5500":"https://badgerclaw.ai")});function Uo(){return Te}function xr(e){if(!e)return null;let t=e.split(".");if(t.length!==3)return null;try{let o=t[1].replace(/-/g,"+").replace(/_/g,"/"),n=o.length%4===0?o:o+"=".repeat(4-o.length%4),r=JSON.parse(Buffer.from(n,"base64").toString("utf8"));return(typeof r?.sub=="string"?r.sub:null)||null}catch{return null}}async function Ft(){let e=S();if(!e?.refresh_token||!e?.email)return Te=e?e.refresh_token?"no email in auth.json \u2014 re-run `badgerclaw login`":"no refresh_token in auth.json \u2014 re-run `badgerclaw login`":"not logged in (auth.json missing)",null;let t=xr(e.access_token);try{let o=await Le.default.post(`${it}/api/v1/user/token/refresh`,{refresh_token:e.refresh_token,email:e.email,...t?{cognito_username:t}:{}}),n=o.data?.result??o.data,r=n?.access_token;if(!r)return Te="server returned no access_token",null;let s=n.expires_in||3600,a=new Date(Date.now()+s*1e3).toISOString();return ot({...e,access_token:r,expires_at:a}),Te=null,r}catch(o){let n=o?.response?.status,r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";Te=n?`HTTP ${n}: ${r}`:`network error: ${r}`;let s=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(n===403&&Mo.test(s))throw De(),new ve(s);return null}}function Ht(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 Fo(e){return e.interceptors.response.use(void 0,t=>{if(t.response?.status===403){let n=t.message||t.response?.data?.errors?.[0]||t.response?.data?.detail||"";if(Mo.test(n))return De(),Promise.reject(new ve(n))}return Promise.reject(t)}),e}function Ho(e){return e.interceptors.response.use(void 0,async t=>{let o=t.config;if(t.response?.status!==401||o._retried)return Promise.reject(t);o._retried=!0,at||(at=Ft().finally(()=>{at=null}));let n=await at;return n?(o.headers.Authorization=`Bearer ${n}`,e.request(o)):Promise.reject(t)}),e}function E(){let e=S(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=Le.default.create({baseURL:it,headers:t});return Ht(o),Ho(o),Fo(o),o}function Go(){return Ht(Le.default.create({baseURL:it,headers:{"Content-Type":"application/json"}}))}function Ne(e){let t=Le.default.create({baseURL:it,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return Ht(t),Ho(t),Fo(t),t}var Le,it,ve,Mo,at,Te,de=L(()=>{"use strict";Le=d(require("axios"));N();ne();it=j,ve=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},Mo=/account\s+has\s+been\s+(deleted|deactivated)/i,at=null,Te=null});function qo(){try{let e=re.default.statSync(ue);return Date.now()-e.mtimeMs>Wo}catch{return!0}}function Gt(){try{return re.default.mkdirSync(Vt.default.dirname(ue),{recursive:!0}),re.default.writeFileSync(ue,String(process.pid),{flag:"wx"}),!0}catch{if(qo())try{return re.default.unlinkSync(ue),re.default.writeFileSync(ue,String(process.pid),{flag:"wx"}),!0}catch{return!1}return!1}}function Jo(){try{re.default.unlinkSync(ue)}catch{}}async function Yo(e){let t=!1;for(let o=0;o<Rr;o++){if(Gt()){t=!0;break}await new Promise(n=>setTimeout(n,Ko))}t||console.warn("[config-lock] Could not acquire lock after timeout \u2014 proceeding without lock");try{return await e()}finally{t&&Jo()}}function me(e){let t=Gt();if(!t&&qo()){try{re.default.unlinkSync(ue)}catch{}t=Gt()}try{return e()}finally{t&&Jo()}}var re,Vo,Vt,ue,Wo,Ko,Rr,je=L(()=>{"use strict";re=d(require("fs")),Vo=d(require("os")),Vt=d(require("path")),ue=Vt.default.join(Vo.default.homedir(),".openclaw","openclaw.json.lock"),Wo=1e4,Ko=50,Rr=Math.ceil(Wo/Ko)});var pe=kr((Na,Ar)=>{Ar.exports={name:"badgerclaw",version:"0.2.58",description:"BadgerClaw CLI \u2014 one-click bot provisioning",main:"dist/index.js",bin:{badgerclaw:"./dist/index.js"},files:["dist/","scripts/","assets/","README.md"],scripts:{build:"node build.mjs","verify-dist-version":`node -e "const v=require('./package.json').version; const d=require('fs').readFileSync('./dist/index.js','utf8'); if(!d.includes('version:\\"'+v+'\\"')){console.error('dist/index.js is stale \u2014 rebuild before publish (package.json='+v+')'); process.exit(1);} console.log('dist/index.js OK \u2014 version '+v);"`,prepublishOnly:"rm -rf dist && npm run build && npm run verify-dist-version",preuninstall:"node scripts/preuninstall.cjs",test:"tsx --test 'tests/**/*.test.ts'"},keywords:[],author:"",license:"ISC",dependencies:{"@modelcontextprotocol/sdk":"^1.29.0",axios:"^1.6.0",chalk:"^4.1.2",commander:"^12.0.0",eventsource:"^1.1.2",open:"^8.4.2",ora:"^5.4.1"},devDependencies:{"@types/eventsource":"^1.1.15","@types/node":"^20.0.0",esbuild:"^0.28.0",tsx:"^4.22.0",typescript:"^5.3.0"}}});function lt(e=Tr){try{return Kt.default.readdirSync(e,{withFileTypes:!0}).filter(t=>t.isDirectory()&&t.name.startsWith("badgerclaw-connect-")).map(t=>Y.default.join(e,t.name))}catch{return[]}}function Lr(){return[...lt().map(t=>Y.default.join(t,"node_modules/@badgerclaw/connect/package.json")),Y.default.join(Dr,"package.json"),Y.default.join(zo,"node_modules/@badgerclaw/connect/package.json"),Y.default.join(zo,"package.json")]}function qt(){return"0.2.58"}function dt(){for(let e of Lr())try{let t=Kt.default.readFileSync(e,"utf-8"),o=JSON.parse(t);if(o.version&&(!o.name||o.name==="@badgerclaw/connect"||o.name==="badgerclaw")||o.version)return o.version}catch{}return null}function Nr(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function U(){if((0,Wt.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,Wt.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:Nr(t.stdout)||null}async function jr(){let e=new AbortController,t=setTimeout(()=>e.abort(),Pr);try{let o=await fetch(Er,{signal:e.signal});if(!o.ok)return null;let n=await o.json(),r=n.result&&typeof n.result=="object"?n.result:n;return{cli:r.cli??"unknown",plugin:r.plugin??"unknown",supported_openclaw:r.supported_openclaw??"unknown"}}catch{return null}finally{clearTimeout(t)}}function Br(e){let t=[];if(e.cli&&e.cli!=="unknown"){let n=qt();n!==e.cli&&t.push({component:"cli",current:n,approved:e.cli})}if(!(U()!==null))return t;if(e.plugin&&e.plugin!=="unknown"){let n=dt();(n===null||n!==e.plugin)&&t.push({component:"plugin",current:n??"not installed",approved:e.plugin})}if(e.supported_openclaw&&e.supported_openclaw!=="unknown"){let n=U();(n===null||n!==e.supported_openclaw)&&t.push({component:"openclaw",current:n??"not installed",approved:e.supported_openclaw})}return t}function Mr(e){return e[2]}function Ur(e){return!e||e.startsWith("-")?!0:Or.has(e)}function Fr(e){let t=[];t.push(""),t.push(se.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let n=o.component.padEnd(8);t.push(` ${n} ${se.default.yellow(o.current)} \u2192 ${se.default.green(o.approved)} ${se.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(se.default.green(" To fix, run:")),t.push(se.default.green.bold(" badgerclaw setup")),t.push(""),t.push(se.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
3
- `)}async function Xo(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=Mr(e);if(Ur(t))return;let o=await jr();if(!o)return;let n=Br(o);n.length!==0&&(process.stderr.write(Fr(n)),process.exit(1))}var Kt,ct,Y,Wt,se,Er,Pr,Or,zo,Dr,Tr,Ce=L(()=>{"use strict";Kt=d(require("fs")),ct=d(require("os")),Y=d(require("path")),Wt=require("child_process"),se=d(require("chalk"));ne();Er=`${j}/api/v1/dashboard/versions/latest`,Pr=2500,Or=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),zo=Y.default.join(ct.default.homedir(),".openclaw/extensions/badgerclaw"),Dr=Y.default.join(ct.default.homedir(),".openclaw/npm/node_modules/@badgerclaw/connect"),Tr=Y.default.join(ct.default.homedir(),".openclaw/npm/projects")});var on={};Nt(on,{HERMES_IMAGE_DEFAULT:()=>Ie,detectCapabilities:()=>ge,detectDiskFreeGb:()=>tn,detectDocker:()=>ut,detectHermes:()=>mt,detectOpenClaw:()=>en});function ut(){if((0,Be.spawnSync)("which",["docker"],{encoding:"utf-8"}).status!==0)return{installed:!1};let t=(0,Be.spawnSync)("docker",["version","--format","{{.Server.Version}}"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout.trim()?{installed:!1}:{installed:!0,version:t.stdout.trim()}}function en(){let e=U();return e?{installed:!0,version:e}:{installed:!1}}function mt(e){if(!e.installed)return{installed:!1};let t=process.env.HERMES_IMAGE||Ie;return(0,Be.spawnSync)("docker",["image","inspect","--format","{{.RepoDigests}}",t],{encoding:"utf-8",timeout:3e3}).status!==0?{installed:!1}:{installed:!0,image:t}}function tn(){let e=Zo.default.join(Jt.default.homedir(),".badgerclaw"),t=Qo.default.existsSync(e)?e:Jt.default.homedir();if(process.platform==="win32")return null;let o=(0,Be.spawnSync)("df",["-Pk",t],{encoding:"utf-8",timeout:3e3});if(o.status!==0||!o.stdout)return null;let n=o.stdout.trim().split(`
4
- `);if(n.length<2)return null;let r=n[1].split(/\s+/),s=parseInt(r[3]||"",10);return Number.isFinite(s)?Math.floor(s/1024/1024):null}function ge(){let e=ut();return{openclaw:en(),hermes:mt(e),docker:e,disk_free_gb:tn(),ports_in_use:[]}}var Be,Qo,Jt,Zo,Ie,fe=L(()=>{"use strict";Be=require("child_process"),Qo=d(require("fs")),Jt=d(require("os")),Zo=d(require("path"));Ce();Ie="hermes-agent-bc:bundled"});function gt(e){return q.default.join(Hr,`bot-${e}`)}function Xt(e){return`badgerclaw-hermes-bot-${e}`}function Qt(){if(!P.default.existsSync(Yt))return{hermes_bots:{}};try{let e=P.default.readFileSync(Yt,"utf-8"),t=JSON.parse(e);return{hermes_bots:t.hermes_bots&&typeof t.hermes_bots=="object"?t.hermes_bots:{}}}catch{return{hermes_bots:{}}}}function Vr(e){P.default.existsSync(pt)||P.default.mkdirSync(pt,{recursive:!0,mode:448}),P.default.writeFileSync(Yt,JSON.stringify(e,null,2)+`
5
- `,{mode:384})}function Wr(e,t=Gr){let o=new Set(Object.values(e.hermes_bots).map(r=>r.port)),n=t;for(;o.has(n)||!Kr(n);)if(n+=1,n-t>1e3)throw new Error(`Could not find a free port near ${t} after 1000 tries \u2014 host is unusually busy`);return n}function Kr(e){let t=rn.default.createServer(),o=!1;try{t.listen(e,"127.0.0.1"),o=!0}catch{o=!1}finally{try{t.close()}catch{}}return o}function an(e=process.env){let t=e.BADGERCLAW_LLM_PROVIDER?.toLowerCase(),o=e.BADGERCLAW_LLM_API_KEY;if(t&&o){if(t!=="gemini"&&t!=="anthropic"&&t!=="openrouter")throw new Error(`BADGERCLAW_LLM_PROVIDER must be one of: gemini, anthropic, openrouter. Got '${t}'.`);return{provider:t,apiKey:o}}let n=e.GOOGLE_API_KEY||e.GEMINI_API_KEY;if(n)return{provider:"gemini",apiKey:n};if(e.ANTHROPIC_API_KEY)return{provider:"anthropic",apiKey:e.ANTHROPIC_API_KEY};if(e.OPENROUTER_API_KEY)return{provider:"openrouter",apiKey:e.OPENROUTER_API_KEY}}function qr(e){switch(e){case"gemini":return"gemini-2.5-flash";case"anthropic":return"claude-sonnet-4-6";case"openrouter":return"anthropic/claude-sonnet-4-6"}}function Jr(e){switch(e){case"gemini":return"GOOGLE_API_KEY";case"anthropic":return"ANTHROPIC_API_KEY";case"openrouter":return"OPENROUTER_API_KEY"}}function Yr(e,t){let o=[`# Generated by badgerclaw CLI for bot ${e.botId}.`,"# Edit at your own risk; subsequent pair operations may overwrite.","",`MATRIX_HOMESERVER=${e.matrixHomeserver}`,`MATRIX_ACCESS_TOKEN=${e.matrixAccessToken}`,`MATRIX_USER_ID=${e.matrixUserId}`,`MATRIX_DEVICE_ID=${e.matrixDeviceId}`,"MATRIX_ENCRYPTION=true",`MATRIX_ALLOWED_USERS=${e.ownerMatrixUserId}`];return e.homeRoomId&&o.push(`MATRIX_HOME_ROOM=${e.homeRoomId}`),e.llm&&(o.push(""),o.push("# LLM provider \u2014 set by the operator's environment at pair time."),o.push("# Hermes reads this directly; model selection lives in config.yaml."),o.push(`${Jr(e.llm.provider)}=${e.llm.apiKey}`)),o.push("","# OpenAI-compatible API surface \u2014 localhost only by default so the","# CLI's daemon can health-check the container without exposing it","# beyond the host loopback.","API_SERVER_ENABLED=true","API_SERVER_HOST=127.0.0.1",`API_SERVER_PORT=${t}`),o.join(`
2
+ "use strict";var $r=Object.create;var tt=Object.defineProperty;var vr=Object.getOwnPropertyDescriptor;var Cr=Object.getOwnPropertyNames;var Ir=Object.getPrototypeOf,kr=Object.prototype.hasOwnProperty;var L=(e,t)=>()=>(e&&(t=e(e=0)),t);var xr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Nt=(e,t)=>{for(var o in t)tt(e,o,{get:t[o],enumerable:!0})},Eo=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Cr(t))!kr.call(e,r)&&r!==o&&tt(e,r,{get:()=>t[r],enumerable:!(n=vr(t,r))||n.enumerable});return e};var d=(e,t,o)=>(o=e!=null?$r(Ir(e)):{},Eo(t||!e||!e.__esModule?tt(o,"default",{value:e,enumerable:!0}):o,e)),Po=e=>Eo(tt({},"__esModule",{value:!0}),e);function S(){try{let e=Oe.default.readFileSync(Mt,"utf-8");return JSON.parse(e)}catch{return null}}function ot(e){Oe.default.mkdirSync(Lo,{recursive:!0}),Oe.default.writeFileSync(Mt,JSON.stringify(e,null,2),{mode:384})}function De(){try{Oe.default.unlinkSync(Mt)}catch{}}function nt(){let e=S();return e?new Date(e.expires_at)>new Date:!1}function rt(e){let t=e.match(/^@?([^:]+)/);return t?t[1]:e}var Oe,Bt,To,Lo,Mt,N=L(()=>{"use strict";Oe=d(require("fs")),Bt=d(require("path")),To=d(require("os")),Lo=Bt.default.join(To.default.homedir(),".badgerclaw"),Mt=Bt.default.join(Lo,"auth.json")});function Ut(){return No.default.createHash("sha256").update(`${W.default.hostname()}-${W.default.platform()}-${W.default.arch()}`).digest("hex").slice(0,16)}function K(){let e=S();if(e?.instance_id)return e.instance_id;let t=Ut();return`openclaw-${W.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${t}`}function st(){return{hostname:W.default.hostname(),os:W.default.platform(),arch:W.default.arch(),uptimeSeconds:Math.floor(W.default.uptime()),memFreeMb:Math.floor(W.default.freemem()/1024/1024)}}var W,No,$e=L(()=>{"use strict";W=d(require("os")),No=d(require("crypto"));N()});var jo,j,Bo,ne=L(()=>{"use strict";jo=process.env.BADGERCLAW_ENV==="local",j=process.env.BADGERCLAW_API_URL??(jo?"http://localhost:8000":"https://api.badger.signout.io"),Bo=process.env.BADGERCLAW_AUTH_URL??(jo?"http://localhost:5500":"https://badgerclaw.ai")});function Uo(){return Te}function Rr(e){if(!e)return null;let t=e.split(".");if(t.length!==3)return null;try{let o=t[1].replace(/-/g,"+").replace(/_/g,"/"),n=o.length%4===0?o:o+"=".repeat(4-o.length%4),r=JSON.parse(Buffer.from(n,"base64").toString("utf8"));return(typeof r?.sub=="string"?r.sub:null)||null}catch{return null}}async function Ft(){let e=S();if(!e?.refresh_token||!e?.email)return Te=e?e.refresh_token?"no email in auth.json \u2014 re-run `badgerclaw login`":"no refresh_token in auth.json \u2014 re-run `badgerclaw login`":"not logged in (auth.json missing)",null;let t=Rr(e.access_token);try{let o=await Le.default.post(`${it}/api/v1/user/token/refresh`,{refresh_token:e.refresh_token,email:e.email,...t?{cognito_username:t}:{}}),n=o.data?.result??o.data,r=n?.access_token;if(!r)return Te="server returned no access_token",null;let s=n.expires_in||3600,a=new Date(Date.now()+s*1e3).toISOString();return ot({...e,access_token:r,expires_at:a}),Te=null,r}catch(o){let n=o?.response?.status,r=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"unknown error";Te=n?`HTTP ${n}: ${r}`:`network error: ${r}`;let s=o?.response?.data?.errors?.[0]||o?.response?.data?.detail||o?.message||"";if(n===403&&Mo.test(s))throw De(),new ve(s);return null}}function Ht(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 Fo(e){return e.interceptors.response.use(void 0,t=>{if(t.response?.status===403){let n=t.message||t.response?.data?.errors?.[0]||t.response?.data?.detail||"";if(Mo.test(n))return De(),Promise.reject(new ve(n))}return Promise.reject(t)}),e}function Ho(e){return e.interceptors.response.use(void 0,async t=>{let o=t.config;if(t.response?.status!==401||o._retried)return Promise.reject(t);o._retried=!0,at||(at=Ft().finally(()=>{at=null}));let n=await at;return n?(o.headers.Authorization=`Bearer ${n}`,e.request(o)):Promise.reject(t)}),e}function E(){let e=S(),t={"Content-Type":"application/json"};e&&(t.Authorization=`Bearer ${e.access_token}`);let o=Le.default.create({baseURL:it,headers:t});return Ht(o),Ho(o),Fo(o),o}function Go(){return Ht(Le.default.create({baseURL:it,headers:{"Content-Type":"application/json"}}))}function Ne(e){let t=Le.default.create({baseURL:it,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}});return Ht(t),Ho(t),Fo(t),t}var Le,it,ve,Mo,at,Te,de=L(()=>{"use strict";Le=d(require("axios"));N();ne();it=j,ve=class extends Error{constructor(o){super(o);this.code="DEACTIVATED";this.name="DeactivatedError"}},Mo=/account\s+has\s+been\s+(deleted|deactivated)/i,at=null,Te=null});function qo(){try{let e=re.default.statSync(ue);return Date.now()-e.mtimeMs>Wo}catch{return!0}}function Gt(){try{return re.default.mkdirSync(Vt.default.dirname(ue),{recursive:!0}),re.default.writeFileSync(ue,String(process.pid),{flag:"wx"}),!0}catch{if(qo())try{return re.default.unlinkSync(ue),re.default.writeFileSync(ue,String(process.pid),{flag:"wx"}),!0}catch{return!1}return!1}}function Jo(){try{re.default.unlinkSync(ue)}catch{}}async function Yo(e){let t=!1;for(let o=0;o<Ar;o++){if(Gt()){t=!0;break}await new Promise(n=>setTimeout(n,Ko))}t||console.warn("[config-lock] Could not acquire lock after timeout \u2014 proceeding without lock");try{return await e()}finally{t&&Jo()}}function me(e){let t=Gt();if(!t&&qo()){try{re.default.unlinkSync(ue)}catch{}t=Gt()}try{return e()}finally{t&&Jo()}}var re,Vo,Vt,ue,Wo,Ko,Ar,je=L(()=>{"use strict";re=d(require("fs")),Vo=d(require("os")),Vt=d(require("path")),ue=Vt.default.join(Vo.default.homedir(),".openclaw","openclaw.json.lock"),Wo=1e4,Ko=50,Ar=Math.ceil(Wo/Ko)});var pe=xr((ja,Er)=>{Er.exports={name:"badgerclaw",version:"0.2.59",description:"BadgerClaw CLI \u2014 one-click bot provisioning",main:"dist/index.js",bin:{badgerclaw:"./dist/index.js"},files:["dist/","scripts/","assets/","README.md"],scripts:{build:"node build.mjs","verify-dist-version":`node -e "const v=require('./package.json').version; const d=require('fs').readFileSync('./dist/index.js','utf8'); if(!d.includes('version:\\"'+v+'\\"')){console.error('dist/index.js is stale \u2014 rebuild before publish (package.json='+v+')'); process.exit(1);} console.log('dist/index.js OK \u2014 version '+v);"`,prepublishOnly:"rm -rf dist && npm run build && npm run verify-dist-version",preuninstall:"node scripts/preuninstall.cjs",test:"tsx --test 'tests/**/*.test.ts'"},keywords:[],author:"",license:"ISC",dependencies:{"@modelcontextprotocol/sdk":"^1.29.0",axios:"^1.6.0",chalk:"^4.1.2",commander:"^12.0.0",eventsource:"^1.1.2",open:"^8.4.2",ora:"^5.4.1"},devDependencies:{"@types/eventsource":"^1.1.15","@types/node":"^20.0.0",esbuild:"^0.28.0",tsx:"^4.22.0",typescript:"^5.3.0"}}});function lt(e=Lr){try{return Kt.default.readdirSync(e,{withFileTypes:!0}).filter(t=>t.isDirectory()&&t.name.startsWith("badgerclaw-connect-")).map(t=>Y.default.join(e,t.name))}catch{return[]}}function Nr(){return[...lt().map(t=>Y.default.join(t,"node_modules/@badgerclaw/connect/package.json")),Y.default.join(Tr,"package.json"),Y.default.join(zo,"node_modules/@badgerclaw/connect/package.json"),Y.default.join(zo,"package.json")]}function qt(){return"0.2.59"}function dt(){for(let e of Nr())try{let t=Kt.default.readFileSync(e,"utf-8"),o=JSON.parse(t);if(o.version&&(!o.name||o.name==="@badgerclaw/connect"||o.name==="badgerclaw")||o.version)return o.version}catch{}return null}function jr(e){let t=e.trim(),o=t.match(/\d+(?:\.\d+){1,3}/);return o?o[0]:t}function U(){if((0,Wt.spawnSync)("which",["openclaw"],{encoding:"utf-8"}).status!==0)return null;let t=(0,Wt.spawnSync)("openclaw",["--version"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout?null:jr(t.stdout)||null}async function Br(){let e=new AbortController,t=setTimeout(()=>e.abort(),Or);try{let o=await fetch(Pr,{signal:e.signal});if(!o.ok)return null;let n=await o.json(),r=n.result&&typeof n.result=="object"?n.result:n;return{cli:r.cli??"unknown",plugin:r.plugin??"unknown",supported_openclaw:r.supported_openclaw??"unknown"}}catch{return null}finally{clearTimeout(t)}}function Mr(e){let t=[];if(e.cli&&e.cli!=="unknown"){let n=qt();n!==e.cli&&t.push({component:"cli",current:n,approved:e.cli})}if(!(U()!==null))return t;if(e.plugin&&e.plugin!=="unknown"){let n=dt();(n===null||n!==e.plugin)&&t.push({component:"plugin",current:n??"not installed",approved:e.plugin})}if(e.supported_openclaw&&e.supported_openclaw!=="unknown"){let n=U();(n===null||n!==e.supported_openclaw)&&t.push({component:"openclaw",current:n??"not installed",approved:e.supported_openclaw})}return t}function Ur(e){return e[2]}function Fr(e){return!e||e.startsWith("-")?!0:Dr.has(e)}function Hr(e){let t=[];t.push(""),t.push(se.default.red.bold("\u2717 Unsupported versions detected")),t.push("");for(let o of e){let n=o.component.padEnd(8);t.push(` ${n} ${se.default.yellow(o.current)} \u2192 ${se.default.green(o.approved)} ${se.default.dim("(supported)")}`)}return t.push(""),t.push("This command is blocked until your installation matches the supported versions."),t.push(""),t.push(se.default.green(" To fix, run:")),t.push(se.default.green.bold(" badgerclaw setup")),t.push(""),t.push(se.default.dim(" (bypass temporarily: BADGERCLAW_NO_VERSION_CHECK=1 badgerclaw <cmd>)")),t.push(""),t.join(`
3
+ `)}async function Xo(e){if(process.env.BADGERCLAW_NO_VERSION_CHECK)return;let t=Ur(e);if(Fr(t))return;let o=await Br();if(!o)return;let n=Mr(o);n.length!==0&&(process.stderr.write(Hr(n)),process.exit(1))}var Kt,ct,Y,Wt,se,Pr,Or,Dr,zo,Tr,Lr,Ce=L(()=>{"use strict";Kt=d(require("fs")),ct=d(require("os")),Y=d(require("path")),Wt=require("child_process"),se=d(require("chalk"));ne();Pr=`${j}/api/v1/dashboard/versions/latest`,Or=2500,Dr=new Set(["setup","logout","help","--version","-V","--help","-h","heartbeat","watch","autopair"]),zo=Y.default.join(ct.default.homedir(),".openclaw/extensions/badgerclaw"),Tr=Y.default.join(ct.default.homedir(),".openclaw/npm/node_modules/@badgerclaw/connect"),Lr=Y.default.join(ct.default.homedir(),".openclaw/npm/projects")});var on={};Nt(on,{HERMES_IMAGE_DEFAULT:()=>Ie,detectCapabilities:()=>ge,detectDiskFreeGb:()=>tn,detectDocker:()=>ut,detectHermes:()=>mt,detectOpenClaw:()=>en});function ut(){if((0,Be.spawnSync)("which",["docker"],{encoding:"utf-8"}).status!==0)return{installed:!1};let t=(0,Be.spawnSync)("docker",["version","--format","{{.Server.Version}}"],{encoding:"utf-8",timeout:3e3});return t.status!==0||!t.stdout.trim()?{installed:!1}:{installed:!0,version:t.stdout.trim()}}function en(){let e=U();return e?{installed:!0,version:e}:{installed:!1}}function mt(e){if(!e.installed)return{installed:!1};let t=process.env.HERMES_IMAGE||Ie;return(0,Be.spawnSync)("docker",["image","inspect","--format","{{.RepoDigests}}",t],{encoding:"utf-8",timeout:3e3}).status!==0?{installed:!1}:{installed:!0,image:t}}function tn(){let e=Zo.default.join(Jt.default.homedir(),".badgerclaw"),t=Qo.default.existsSync(e)?e:Jt.default.homedir();if(process.platform==="win32")return null;let o=(0,Be.spawnSync)("df",["-Pk",t],{encoding:"utf-8",timeout:3e3});if(o.status!==0||!o.stdout)return null;let n=o.stdout.trim().split(`
4
+ `);if(n.length<2)return null;let r=n[1].split(/\s+/),s=parseInt(r[3]||"",10);return Number.isFinite(s)?Math.floor(s/1024/1024):null}function ge(){let e=ut();return{openclaw:en(),hermes:mt(e),docker:e,disk_free_gb:tn(),ports_in_use:[]}}var Be,Qo,Jt,Zo,Ie,fe=L(()=>{"use strict";Be=require("child_process"),Qo=d(require("fs")),Jt=d(require("os")),Zo=d(require("path"));Ce();Ie="hermes-agent-bc:bundled"});function gt(e){return q.default.join(Gr,`bot-${e}`)}function Xt(e){return`badgerclaw-hermes-bot-${e}`}function Qt(){if(!P.default.existsSync(Yt))return{hermes_bots:{}};try{let e=P.default.readFileSync(Yt,"utf-8"),t=JSON.parse(e);return{hermes_bots:t.hermes_bots&&typeof t.hermes_bots=="object"?t.hermes_bots:{}}}catch{return{hermes_bots:{}}}}function Wr(e){P.default.existsSync(pt)||P.default.mkdirSync(pt,{recursive:!0,mode:448}),P.default.writeFileSync(Yt,JSON.stringify(e,null,2)+`
5
+ `,{mode:384})}function Kr(e,t=Vr){let o=new Set(Object.values(e.hermes_bots).map(r=>r.port)),n=t;for(;o.has(n)||!qr(n);)if(n+=1,n-t>1e3)throw new Error(`Could not find a free port near ${t} after 1000 tries \u2014 host is unusually busy`);return n}function qr(e){let t=sn.default.createServer(),o=!1;try{t.listen(e,"127.0.0.1"),o=!0}catch{o=!1}finally{try{t.close()}catch{}}return o}function cn(e=process.env){let t=e.BADGERCLAW_LLM_PROVIDER?.toLowerCase(),o=e.BADGERCLAW_LLM_API_KEY;if(t&&o){if(t!=="gemini"&&t!=="anthropic"&&t!=="openrouter")throw new Error(`BADGERCLAW_LLM_PROVIDER must be one of: gemini, anthropic, openrouter. Got '${t}'.`);return{provider:t,apiKey:o}}let n=e.GOOGLE_API_KEY||e.GEMINI_API_KEY;if(n)return{provider:"gemini",apiKey:n};if(e.ANTHROPIC_API_KEY)return{provider:"anthropic",apiKey:e.ANTHROPIC_API_KEY};if(e.OPENROUTER_API_KEY)return{provider:"openrouter",apiKey:e.OPENROUTER_API_KEY}}function Jr(e){switch(e){case"gemini":return"gemini-2.5-flash";case"anthropic":return"claude-sonnet-4-6";case"openrouter":return"anthropic/claude-sonnet-4-6"}}function Yr(e){switch(e){case"gemini":return"GOOGLE_API_KEY";case"anthropic":return"ANTHROPIC_API_KEY";case"openrouter":return"OPENROUTER_API_KEY"}}function zr(e,t){let o=[`# Generated by badgerclaw CLI for bot ${e.botId}.`,"# Edit at your own risk; subsequent pair operations may overwrite.","",`MATRIX_HOMESERVER=${e.matrixHomeserver}`,`MATRIX_ACCESS_TOKEN=${e.matrixAccessToken}`,`MATRIX_USER_ID=${e.matrixUserId}`,`MATRIX_DEVICE_ID=${e.matrixDeviceId}`,"MATRIX_ENCRYPTION=true",`MATRIX_ALLOWED_USERS=${e.ownerMatrixUserId}`];return e.homeRoomId&&o.push(`MATRIX_HOME_ROOM=${e.homeRoomId}`),e.llm&&(o.push(""),o.push("# LLM provider \u2014 set by the operator's environment at pair time."),o.push("# Hermes reads this directly; model selection lives in config.yaml."),o.push(`${Yr(e.llm.provider)}=${e.llm.apiKey}`)),o.push("","# OpenAI-compatible API surface \u2014 localhost only by default so the","# CLI's daemon can health-check the container without exposing it","# beyond the host loopback.","API_SERVER_ENABLED=true","API_SERVER_HOST=127.0.0.1",`API_SERVER_PORT=${t}`,`API_SERVER_KEY=${(0,rn.randomBytes)(24).toString("hex")}`),o.join(`
6
6
  `)+`
7
- `}function zr(e){let t=[`# Hermes agent config for BadgerClaw bot ${e.botId}.`,"# Generated by badgerclaw CLI; secrets live in the sibling .env file.",""];return e.llm&&t.push("model:",` default: ${qr(e.llm.provider)}`,` provider: ${e.llm.provider}`,""),t.push("agent:",` name: ${e.botName||"BadgerClaw bot"}`,"terminal:"," backend: local","subagents:"," max_spawn_depth: 1","cron:"," enabled: false",""),t.join(`
8
- `)}function Xr(e){return[`# ${e.botName||"BadgerClaw bot"}`,"","You are a helpful assistant connected to the BadgerClaw platform via Matrix.","Respond concisely. Honour @mentions. Decline to act on rooms you weren't added to.",""].join(`
9
- `)}function Qr(e,t){let o=gt(e.botId);P.default.mkdirSync(o,{recursive:!0,mode:448});let n=q.default.join(o,".env"),r=q.default.join(o,"config.yaml"),s=q.default.join(o,"SOUL.md");return P.default.writeFileSync(n,Yr(e,t),{mode:384}),P.default.writeFileSync(r,zr(e),{mode:384}),P.default.existsSync(s)||P.default.writeFileSync(s,Xr(e),{mode:384}),{dataDir:o,envPath:n,configPath:r,soulPath:s}}function Zr(e){let t=process.getuid?.()??0,o=process.getgid?.()??0,n=["run","-d","--name",e.containerName,"--restart","unless-stopped","-v",`${e.dataDir}:/opt/data`,"-p",`127.0.0.1:${e.port}:${e.port}`];return t>0&&n.push("-e",`HERMES_UID=${t}`),o>0&&n.push("-e",`HERMES_GID=${o}`),n.push("--env-file",`${e.dataDir}/.env`,e.image,"gateway","run"),n}function cn(e,t={}){let o=t.docker??zt,n=e.image||process.env.HERMES_IMAGE||Ie;e.llm||console.warn(`[hermes] no LLM provider configured for bot ${e.botId}. Set BADGERCLAW_LLM_PROVIDER + BADGERCLAW_LLM_API_KEY (or one of GOOGLE_API_KEY / ANTHROPIC_API_KEY / OPENROUTER_API_KEY) and re-pair, or the bot will join rooms but be unable to reply.`);let r=Qt(),s=r.hermes_bots[e.botId],a=s?.port??Wr(r,t.portBase),l=s?.container_name??Xt(e.botId);if(Qr(e,a),!t.skipDocker){o.run(["rm","-f",l]);let i=Zr({containerName:l,dataDir:gt(e.botId),port:a,image:n}),u=o.run(i);if(u.status!==0)throw new Error(`docker run failed (exit ${u.status}): ${u.stderr||u.stdout}`)}let c={bot_id:e.botId,runtime:"hermes",container_name:l,port:a,data_dir:gt(e.botId),image:n,started_at:new Date().toISOString()};return r.hermes_bots[e.botId]=c,Vr(r),c}function ln(e={}){let t=e.docker??zt,o=Qt(),n=[];for(let[r,s]of Object.entries(o.hermes_bots)){let a=t.run(["inspect","--format","{{.State.Status}}",s.container_name]),l,c=a.stdout.trim()||null;a.status!==0?(l="missing",c=(a.stderr||a.stdout).trim()||null):c==="running"?l="running":c==="exited"||c==="dead"||c==="created"?l="stopped":l="unknown",n.push({bot_id:r,container_name:s.container_name,status:l,raw:c})}return n}function ts(e){let t=e.match(es);return t?t[1].trim():null}async function Zt(e,t,o,n={}){let r={recoveryKey:null,posted:!1,envUpdated:!1};if(!e.backendBotId)return r;let a=(n.docker??zt).run(["logs",t]),l=`${a.stdout}
10
- ${a.stderr}`,c=ts(l);if(!c)return r;if(r.recoveryKey=c,n.api)try{let u=await n.api.post(`/api/v1/hermes/bots/${e.backendBotId}/runtime-bootstrap`,{recovery_key:c,image_ref:o});r.posted=u.status>=200&&u.status<300}catch(u){console.warn(`[hermes] failed to POST recovery key for ${e.botId}: ${u.message}. Daemon will retry next beat.`)}let i=n.envPath??q.default.join(gt(e.botId),".env");return P.default.existsSync(i)&&(P.default.readFileSync(i,"utf-8").includes("MATRIX_RECOVERY_KEY=")||(P.default.appendFileSync(i,`
7
+ `}function Xr(e){let t=[`# Hermes agent config for BadgerClaw bot ${e.botId}.`,"# Generated by badgerclaw CLI; secrets live in the sibling .env file.",""];return e.llm&&t.push("model:",` default: ${Jr(e.llm.provider)}`,` provider: ${e.llm.provider}`,""),t.push("agent:",` name: ${e.botName||"BadgerClaw bot"}`,"terminal:"," backend: local","subagents:"," max_spawn_depth: 1","cron:"," enabled: false",""),t.join(`
8
+ `)}function Qr(e){return[`# ${e.botName||"BadgerClaw bot"}`,"","You are a helpful assistant connected to the BadgerClaw platform via Matrix.","Respond concisely. Honour @mentions. Decline to act on rooms you weren't added to.",""].join(`
9
+ `)}function Zr(e,t){let o=gt(e.botId);P.default.mkdirSync(o,{recursive:!0,mode:448});let n=q.default.join(o,".env"),r=q.default.join(o,"config.yaml"),s=q.default.join(o,"SOUL.md");return P.default.writeFileSync(n,zr(e,t),{mode:384}),P.default.writeFileSync(r,Xr(e),{mode:384}),P.default.existsSync(s)||P.default.writeFileSync(s,Qr(e),{mode:384}),{dataDir:o,envPath:n,configPath:r,soulPath:s}}function es(e){let t=process.getuid?.()??0,o=process.getgid?.()??0,n=["run","-d","--name",e.containerName,"--restart","unless-stopped","-v",`${e.dataDir}:/opt/data`];return process.env.BADGERCLAW_HERMES_NETWORK==="host"?n.push("--network","host"):n.push("-p",`127.0.0.1:${e.port}:${e.port}`),t>0&&n.push("-e",`HERMES_UID=${t}`),o>0&&n.push("-e",`HERMES_GID=${o}`),n.push("--env-file",`${e.dataDir}/.env`,e.image,"gateway","run"),n}function ln(e,t={}){let o=t.docker??zt,n=e.image||process.env.HERMES_IMAGE||Ie;e.llm||console.warn(`[hermes] no LLM provider configured for bot ${e.botId}. Set BADGERCLAW_LLM_PROVIDER + BADGERCLAW_LLM_API_KEY (or one of GOOGLE_API_KEY / ANTHROPIC_API_KEY / OPENROUTER_API_KEY) and re-pair, or the bot will join rooms but be unable to reply.`);let r=Qt(),s=r.hermes_bots[e.botId],a=s?.port??Kr(r,t.portBase),l=s?.container_name??Xt(e.botId);if(Zr(e,a),!t.skipDocker){o.run(["rm","-f",l]);let i=es({containerName:l,dataDir:gt(e.botId),port:a,image:n}),u=o.run(i);if(u.status!==0)throw new Error(`docker run failed (exit ${u.status}): ${u.stderr||u.stdout}`)}let c={bot_id:e.botId,runtime:"hermes",container_name:l,port:a,data_dir:gt(e.botId),image:n,started_at:new Date().toISOString()};return r.hermes_bots[e.botId]=c,Wr(r),c}function dn(e={}){let t=e.docker??zt,o=Qt(),n=[];for(let[r,s]of Object.entries(o.hermes_bots)){let a=t.run(["inspect","--format","{{.State.Status}}",s.container_name]),l,c=a.stdout.trim()||null;a.status!==0?(l="missing",c=(a.stderr||a.stdout).trim()||null):c==="running"?l="running":c==="exited"||c==="dead"||c==="created"?l="stopped":l="unknown",n.push({bot_id:r,container_name:s.container_name,status:l,raw:c})}return n}function os(e){let t=e.match(ts);return t?t[1].trim():null}async function Zt(e,t,o,n={}){let r={recoveryKey:null,posted:!1,envUpdated:!1};if(!e.backendBotId)return r;let a=(n.docker??zt).run(["logs",t]),l=`${a.stdout}
10
+ ${a.stderr}`,c=os(l);if(!c)return r;if(r.recoveryKey=c,n.api)try{let u=await n.api.post(`/api/v1/hermes/bots/${e.backendBotId}/runtime-bootstrap`,{recovery_key:c,image_ref:o});r.posted=u.status>=200&&u.status<300}catch(u){console.warn(`[hermes] failed to POST recovery key for ${e.botId}: ${u.message}. Daemon will retry next beat.`)}let i=n.envPath??q.default.join(gt(e.botId),".env");return P.default.existsSync(i)&&(P.default.readFileSync(i,"utf-8").includes("MATRIX_RECOVERY_KEY=")||(P.default.appendFileSync(i,`
11
11
  # Cross-signing recovery key captured from first-boot logs.
12
12
  # Hermes re-uses this on restart to re-sign the device after
13
13
  # Synapse rotates server keys.
14
14
  MATRIX_RECOVERY_KEY=${c}
15
- `),r.envUpdated=!0)),r}async function dn(e={}){let t=Qt(),o=[];for(let[n,r]of Object.entries(t.hermes_bots)){let s=q.default.join(r.data_dir,".env"),a=!1;try{P.default.existsSync(s)&&(a=P.default.readFileSync(s,"utf-8").includes("MATRIX_RECOVERY_KEY="))}catch{}if(a){o.push({bot_id:n,attempted:!1,recoveryKeyFound:!0,posted:!1,envUpdated:!1});continue}if(n.startsWith("@")){o.push({bot_id:n,attempted:!1,recoveryKeyFound:!1,posted:!1,envUpdated:!1});continue}try{let l=await Zt({botId:n,backendBotId:n},r.container_name,r.image,{docker:e.docker,api:e.api,envPath:s});o.push({bot_id:n,attempted:!0,recoveryKeyFound:l.recoveryKey!==null,posted:l.posted,envUpdated:l.envUpdated})}catch(l){console.warn(`[hermes] recovery-key retry failed for ${n}: ${l.message}`),o.push({bot_id:n,attempted:!0,recoveryKeyFound:!1,posted:!1,envUpdated:!1})}}return o}var nn,P,rn,sn,q,pt,Hr,Yt,Gr,zt,es,eo=L(()=>{"use strict";nn=require("child_process"),P=d(require("fs")),rn=d(require("net")),sn=d(require("os")),q=d(require("path"));fe();pt=q.default.join(sn.default.homedir(),".badgerclaw"),Hr=q.default.join(pt,"hermes"),Yt=q.default.join(pt,"state.json"),Gr=8642,zt={run:e=>{let t=(0,nn.spawnSync)("docker",e,{encoding:"utf-8"});return{status:t.status,stdout:t.stdout||"",stderr:t.stderr||""}}};es=/SAVE THIS RECOVERY KEY[\s\S]*?key rotation:\s+((?:[A-Za-z0-9]{4}\s+){7,}[A-Za-z0-9]{4})/});function ft(e){return`'${e.replace(/'/g,"'\\''")}'`}function os(){if(ae!==null)return ae;let e=["/opt/homebrew/lib/node_modules/openclaw/openclaw.mjs","/usr/local/lib/node_modules/openclaw/openclaw.mjs","/usr/lib/node_modules/openclaw/openclaw.mjs"];for(let t of e)if(Me.default.existsSync(t))return ae=`${ft(process.execPath)} ${ft(t)}`,ae;try{let{execSync:t}=require("child_process"),o=t("npm root -g",{encoding:"utf-8",timeout:5e3,stdio:["ignore","pipe","ignore"]}).toString().trim();if(o){let n=no.default.join(o,"openclaw","openclaw.mjs");if(Me.default.existsSync(n))return ae=`${ft(process.execPath)} ${ft(n)}`,ae}}catch{}return ae="openclaw",ae}function to(e,t,o){t?t.fail(F.default.red(o)):e&&console.error(`[autopair] ${o}`)}async function ns(e){if(!e.owner_matrix_user_id)throw new Error("Hermes redeem response missing owner_matrix_user_id. Update the API or fall back to OpenClaw runtime for this bot.");let t=e.user_id.replace(/[^a-zA-Z0-9_.-]/g,"_"),o={botId:e.bot_id??t,backendBotId:e.bot_id??void 0,matrixHomeserver:e.homeserver,matrixAccessToken:e.access_token,matrixUserId:e.user_id,matrixDeviceId:e.device_id,ownerMatrixUserId:e.owner_matrix_user_id,botName:e.bot_name,llm:an()},n=cn(o);if(o.backendBotId){let r=S();if(r){let s=Ne(r.access_token);try{await Zt(o,Xt(o.botId),n.image,{api:{post:async(a,l)=>{let c=await s.post(a,l);return{status:c.status,data:c.data}}}})}catch(a){console.warn(`[hermes] recovery key capture failed for ${o.botId}: ${a.message}. Daemon will retry next beat.`)}}}}async function Ue(e,t,o,n){let r=S();if(!r)return;let s=n?null:(0,oo.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${j}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e,instance_id:K()})});if(!a.ok){if(a.status===410){s?.info(F.default.dim(`${t} already paired (race-loss; another channel redeemed first).`));return}let u=await a.json().catch(()=>({errors:[a.statusText]}));to(n,s,`Failed to redeem ${t}: ${u.errors?.[0]||a.status}`);return}let l=await a.json(),c=l.result??l;if((c.runtime??"openclaw")==="hermes"){try{await ns(c),s?.succeed(F.default.green(`\u2705 ${c.bot_name} (${c.user_id}) running on Hermes \u2014 bot is live!`))}catch(u){to(n,s,`Failed to start Hermes container for ${t}: ${u.message}`)}return}await Yo(async()=>{let u=c.user_id.split(":")[0].replace("@","").replace(/_bot$/,""),p;try{p=JSON.parse(Me.default.readFileSync(un,"utf-8"))}catch{p={}}p.channels||(p.channels={}),p.channels.badgerclaw||(p.channels.badgerclaw={}),p.channels.badgerclaw.accounts||(p.channels.badgerclaw.accounts={});let A={userId:c.user_id,accessToken:c.access_token,homeserver:c.homeserver,encryption:!0,groupPolicy:"open",allowlistOnly:!1,dm:{policy:"open"}};c.device_id&&(A.deviceId=c.device_id),p.channels.badgerclaw.accounts[u]=A,Me.default.writeFileSync(un,JSON.stringify(p,null,2),{mode:384})}),await fetch(`${j}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${r.access_token}`}}).catch(()=>{}),s?.succeed(F.default.green(`\u2705 ${c.bot_name} (${c.user_id}) paired \u2014 bot is live!`))}catch(a){to(n,s,`Failed to pair ${t}: ${a.message}`)}}async function Fe(e=!1){let t=S();if(!t)return 0;let o=Ne(t.access_token);try{let{data:n}=await o.get("/api/v1/openclaw/pending-pairs");if(!n||n.length===0)return 0;let r=new Map;for(let a of n)r.set(a.bot_user_id,a);for(let a of n)r.get(a.bot_user_id)!==a&&await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{});let s=0;for(let a of r.values()){let l=e?null:(0,oo.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await Ue(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),s++}catch(c){l?.fail(F.default.red(`Error pairing ${a.bot_name}: ${c}`))}}if(s>0)try{let{execSync:a}=await import("child_process");a(`${os()} gateway restart`,{stdio:"ignore"}),e||console.log(F.default.green(`
15
+ `),r.envUpdated=!0)),r}async function un(e={}){let t=Qt(),o=[];for(let[n,r]of Object.entries(t.hermes_bots)){let s=q.default.join(r.data_dir,".env"),a=!1;try{P.default.existsSync(s)&&(a=P.default.readFileSync(s,"utf-8").includes("MATRIX_RECOVERY_KEY="))}catch{}if(a){o.push({bot_id:n,attempted:!1,recoveryKeyFound:!0,posted:!1,envUpdated:!1});continue}if(n.startsWith("@")){o.push({bot_id:n,attempted:!1,recoveryKeyFound:!1,posted:!1,envUpdated:!1});continue}try{let l=await Zt({botId:n,backendBotId:n},r.container_name,r.image,{docker:e.docker,api:e.api,envPath:s});o.push({bot_id:n,attempted:!0,recoveryKeyFound:l.recoveryKey!==null,posted:l.posted,envUpdated:l.envUpdated})}catch(l){console.warn(`[hermes] recovery-key retry failed for ${n}: ${l.message}`),o.push({bot_id:n,attempted:!0,recoveryKeyFound:!1,posted:!1,envUpdated:!1})}}return o}var nn,rn,P,sn,an,q,pt,Gr,Yt,Vr,zt,ts,eo=L(()=>{"use strict";nn=require("child_process"),rn=require("crypto"),P=d(require("fs")),sn=d(require("net")),an=d(require("os")),q=d(require("path"));fe();pt=q.default.join(an.default.homedir(),".badgerclaw"),Gr=q.default.join(pt,"hermes"),Yt=q.default.join(pt,"state.json"),Vr=8642,zt={run:e=>{let t=(0,nn.spawnSync)("docker",e,{encoding:"utf-8"});return{status:t.status,stdout:t.stdout||"",stderr:t.stderr||""}}};ts=/SAVE THIS RECOVERY KEY[\s\S]*?key rotation:\s+((?:[A-Za-z0-9]{4}\s+){7,}[A-Za-z0-9]{4})/});function ft(e){return`'${e.replace(/'/g,"'\\''")}'`}function ns(){if(ae!==null)return ae;let e=["/opt/homebrew/lib/node_modules/openclaw/openclaw.mjs","/usr/local/lib/node_modules/openclaw/openclaw.mjs","/usr/lib/node_modules/openclaw/openclaw.mjs"];for(let t of e)if(Me.default.existsSync(t))return ae=`${ft(process.execPath)} ${ft(t)}`,ae;try{let{execSync:t}=require("child_process"),o=t("npm root -g",{encoding:"utf-8",timeout:5e3,stdio:["ignore","pipe","ignore"]}).toString().trim();if(o){let n=no.default.join(o,"openclaw","openclaw.mjs");if(Me.default.existsSync(n))return ae=`${ft(process.execPath)} ${ft(n)}`,ae}}catch{}return ae="openclaw",ae}function to(e,t,o){t?t.fail(F.default.red(o)):e&&console.error(`[autopair] ${o}`)}async function rs(e){if(!e.owner_matrix_user_id)throw new Error("Hermes redeem response missing owner_matrix_user_id. Update the API or fall back to OpenClaw runtime for this bot.");let t=e.user_id.replace(/[^a-zA-Z0-9_.-]/g,"_"),o={botId:e.bot_id??t,backendBotId:e.bot_id??void 0,matrixHomeserver:e.homeserver,matrixAccessToken:e.access_token,matrixUserId:e.user_id,matrixDeviceId:e.device_id,ownerMatrixUserId:e.owner_matrix_user_id,botName:e.bot_name,llm:cn()},n=ln(o);if(o.backendBotId){let r=S();if(r){let s=Ne(r.access_token);try{await Zt(o,Xt(o.botId),n.image,{api:{post:async(a,l)=>{let c=await s.post(a,l);return{status:c.status,data:c.data}}}})}catch(a){console.warn(`[hermes] recovery key capture failed for ${o.botId}: ${a.message}. Daemon will retry next beat.`)}}}}async function Ue(e,t,o,n){let r=S();if(!r)return;let s=n?null:(0,oo.default)(`Pairing bot: ${t}...`).start();try{let a=await fetch(`${j}/api/v1/pairing/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e,instance_id:K()})});if(!a.ok){if(a.status===410){s?.info(F.default.dim(`${t} already paired (race-loss; another channel redeemed first).`));return}let u=await a.json().catch(()=>({errors:[a.statusText]}));to(n,s,`Failed to redeem ${t}: ${u.errors?.[0]||a.status}`);return}let l=await a.json(),c=l.result??l;if((c.runtime??"openclaw")==="hermes"){try{await rs(c),s?.succeed(F.default.green(`\u2705 ${c.bot_name} (${c.user_id}) running on Hermes \u2014 bot is live!`))}catch(u){to(n,s,`Failed to start Hermes container for ${t}: ${u.message}`)}return}await Yo(async()=>{let u=c.user_id.split(":")[0].replace("@","").replace(/_bot$/,""),p;try{p=JSON.parse(Me.default.readFileSync(mn,"utf-8"))}catch{p={}}p.channels||(p.channels={}),p.channels.badgerclaw||(p.channels.badgerclaw={}),p.channels.badgerclaw.accounts||(p.channels.badgerclaw.accounts={});let A={userId:c.user_id,accessToken:c.access_token,homeserver:c.homeserver,encryption:!0,groupPolicy:"open",allowlistOnly:!1,dm:{policy:"open"}};c.device_id&&(A.deviceId=c.device_id),p.channels.badgerclaw.accounts[u]=A,Me.default.writeFileSync(mn,JSON.stringify(p,null,2),{mode:384})}),await fetch(`${j}/api/v1/openclaw/pending-pairs/${e}/claim`,{method:"POST",headers:{Authorization:`Bearer ${r.access_token}`}}).catch(()=>{}),s?.succeed(F.default.green(`\u2705 ${c.bot_name} (${c.user_id}) paired \u2014 bot is live!`))}catch(a){to(n,s,`Failed to pair ${t}: ${a.message}`)}}async function Fe(e=!1){let t=S();if(!t)return 0;let o=Ne(t.access_token);try{let{data:n}=await o.get("/api/v1/openclaw/pending-pairs");if(!n||n.length===0)return 0;let r=new Map;for(let a of n)r.set(a.bot_user_id,a);for(let a of n)r.get(a.bot_user_id)!==a&&await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{});let s=0;for(let a of r.values()){let l=e?null:(0,oo.default)(`Pairing bot: ${a.bot_name} (${a.bot_user_id})`).start();try{await Ue(a.pair_code,a.bot_name,a.bot_user_id,e),await o.post(`/api/v1/openclaw/pending-pairs/${a.pair_code}/claim`).catch(()=>{}),s++}catch(c){l?.fail(F.default.red(`Error pairing ${a.bot_name}: ${c}`))}}if(s>0)try{let{execSync:a}=await import("child_process");a(`${ns()} gateway restart`,{stdio:"ignore"}),e||console.log(F.default.green(`
16
16
  \u26A1 ${s} bot(s) paired \u2014 gateway restarted, bots are live!`))}catch(a){e?console.error(`[autopair] gateway restart after pair failed: ${a?.message||a}`):console.log(F.default.yellow(`
17
- \u26A1 ${s} bot(s) paired. Run: openclaw gateway restart`))}return s}catch{return 0}}var mn,F,oo,pn,no,Me,un,ae,gn,He=L(()=>{"use strict";mn=require("commander"),F=d(require("chalk")),oo=d(require("ora")),pn=d(require("os")),no=d(require("path")),Me=d(require("fs"));N();de();ne();$e();je();eo();un=no.default.join(pn.default.homedir(),".openclaw","openclaw.json");ae=null;gn=new mn.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!S()){console.log(F.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(F.default.dim("Checking for pending bot pairs...")),await Fe(!1)===0&&console.log(F.default.dim("No pending pairs found."))})});async function xs(){try{return await xt.default.get(ks,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function Ye(){try{let t=(await xt.default.get(`${Gn}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(mo=t.pluginVersion),t}catch{return{status:await xs()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:mo,bots:[]}}}function po(e){e&&e!=="unknown"&&(mo=e)}async function Ae(){try{return{success:!0,message:(await xt.default.post(`${Gn}/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 xt,Cs,Gn,Is,ks,mo,ye=L(()=>{"use strict";xt=d(require("axios")),Cs=7331,Gn=`http://localhost:${Cs}`,Is=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,ks=`http://127.0.0.1:${Is}`,mo="unknown"});var Co={};Nt(Co,{getActiveSessions:()=>vo,launchClaudeCode:()=>_o,launchMCPServer:()=>bo,recordSession:()=>So,stopSession:()=>$o});function fo(){try{if(D.default.existsSync(go))return JSON.parse(D.default.readFileSync(go,"utf-8"))}catch{}return[]}function ho(e){D.default.mkdirSync(we,{recursive:!0}),D.default.writeFileSync(go,JSON.stringify(e,null,2))}function Rt(e){try{return process.kill(e,0),!0}catch{return!1}}function Rs(){if(process.env.TMUX)return"tmux";try{if((0,Q.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),D.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function yo(e,t){let o=M.default.join(we,`claude-launcher-${t}.exp`),n=M.default.join(we,`pending-input-${t}.txt`);D.default.writeFileSync(n,"","utf-8");let r=`#!/usr/bin/expect -f
17
+ \u26A1 ${s} bot(s) paired. Run: openclaw gateway restart`))}return s}catch{return 0}}var pn,F,oo,gn,no,Me,mn,ae,fn,He=L(()=>{"use strict";pn=require("commander"),F=d(require("chalk")),oo=d(require("ora")),gn=d(require("os")),no=d(require("path")),Me=d(require("fs"));N();de();ne();$e();je();eo();mn=no.default.join(gn.default.homedir(),".openclaw","openclaw.json");ae=null;fn=new pn.Command("autopair").description("Check for pending bot pairs and connect them to OpenClaw automatically").action(async()=>{if(!S()){console.log(F.default.yellow("Not logged in. Run `badgerclaw login` first."));return}console.log(F.default.dim("Checking for pending bot pairs...")),await Fe(!1)===0&&console.log(F.default.dim("No pending pairs found."))})});async function Rs(){try{return await xt.default.get(xs,{timeout:2e3,validateStatus:()=>!0}),!0}catch{return!1}}async function Ye(){try{let t=(await xt.default.get(`${Vn}/health`,{timeout:5e3})).data;return t.pluginVersion&&t.pluginVersion!=="unknown"&&(mo=t.pluginVersion),t}catch{return{status:await Rs()?"running":"stopped",pid:null,lastRestart:null,pluginVersion:mo,bots:[]}}}function po(e){e&&e!=="unknown"&&(mo=e)}async function Ae(){try{return{success:!0,message:(await xt.default.post(`${Vn}/restart`,{},{timeout:15e3})).data?.message||"Gateway restart initiated"}}catch(e){try{let{execSync:t}=await import("child_process");return t("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted via CLI fallback"}}catch{return{success:!1,message:e.message||"Failed to restart gateway"}}}}var xt,Is,Vn,ks,xs,mo,ye=L(()=>{"use strict";xt=d(require("axios")),Is=7331,Vn=`http://localhost:${Is}`,ks=parseInt(process.env.OPENCLAW_GATEWAY_PORT||"",10)||18789,xs=`http://127.0.0.1:${ks}`,mo="unknown"});var Co={};Nt(Co,{getActiveSessions:()=>vo,launchClaudeCode:()=>_o,launchMCPServer:()=>bo,recordSession:()=>So,stopSession:()=>$o});function fo(){try{if(D.default.existsSync(go))return JSON.parse(D.default.readFileSync(go,"utf-8"))}catch{}return[]}function ho(e){D.default.mkdirSync(we,{recursive:!0}),D.default.writeFileSync(go,JSON.stringify(e,null,2))}function Rt(e){try{return process.kill(e,0),!0}catch{return!1}}function As(){if(process.env.TMUX)return"tmux";try{if((0,Q.execSync)(`osascript -e 'tell application "System Events" to (name of processes) contains "iTerm2"'`,{stdio:"pipe",timeout:3e3}),D.default.existsSync("/Applications/iTerm.app"))return"iterm2"}catch{}return process.platform==="darwin"?"terminal":"direct"}function yo(e,t){let o=M.default.join(we,`claude-launcher-${t}.exp`),n=M.default.join(we,`pending-input-${t}.txt`);D.default.writeFileSync(n,"","utf-8");let r=`#!/usr/bin/expect -f
18
18
  set timeout -1
19
19
  set msgfile "${n}"
20
20
 
@@ -51,7 +51,7 @@ send "\\r"
51
51
  interact timeout 2 {
52
52
  check_and_send_messages
53
53
  }
54
- `;return D.default.mkdirSync(we,{recursive:!0}),D.default.writeFileSync(o,r,{mode:493}),o}function wo(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function As(e,t,o){let n=yo(e,o.BADGERCLAW_SESSION_ID||"default"),r=wo(o),s=`
54
+ `;return D.default.mkdirSync(we,{recursive:!0}),D.default.writeFileSync(o,r,{mode:493}),o}function wo(e){return Object.entries(e).map(([t,o])=>`export ${t}="${o}"`).join("; ")}function Es(e,t,o){let n=yo(e,o.BADGERCLAW_SESSION_ID||"default"),r=wo(o),s=`
55
55
  tell application "iTerm"
56
56
  activate
57
57
  set newWindow to (create window with default profile)
@@ -59,13 +59,13 @@ interact timeout 2 {
59
59
  write text "cd ${At(t)} && ${r} && ${At(n)}"
60
60
  end tell
61
61
  end tell
62
- `;(0,Q.execSync)(`osascript -e '${s.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Es(e,t,o){let n=yo(e,o.BADGERCLAW_SESSION_ID||"default"),r=wo(o),a=`
62
+ `;(0,Q.execSync)(`osascript -e '${s.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Ps(e,t,o){let n=yo(e,o.BADGERCLAW_SESSION_ID||"default"),r=wo(o),a=`
63
63
  tell application "Terminal"
64
64
  activate
65
65
  do script "${`cd ${At(t)} && ${r} && ${At(n)}`.replace(/"/g,'\\"')}"
66
66
  end tell
67
- `;(0,Q.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Ps(e,t,o){let n=yo(e,o.BADGERCLAW_SESSION_ID||"default"),r=wo(o),s=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${r} && ${n}`;(0,Q.execSync)(`tmux new-session -d -s ${s} "${a}"`,{stdio:"pipe",timeout:1e4})}function At(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function bo(e){let t=M.default.join(__dirname,"..","claude-code","mcp-server.js"),o=D.default.existsSync(t)?t:M.default.join(__dirname,"mcp-server.js"),n=(0,Q.spawn)("node",[o],{env:{...process.env,BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},cwd:e.projectDir,stdio:"ignore",detached:!0});return n.unref(),n}function _o(e){let t=M.default.join(M.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=M.default.join(__dirname,"..","claude-code","mcp-server.js"),n=M.default.join(__dirname,"mcp-server.js"),r=D.default.existsSync(t)?t:D.default.existsSync(o)?o:n,s={BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},a=JSON.stringify({mcpServers:{badgerclaw:{command:"node",args:[r],env:s}}}),l=M.default.join(we,`mcp-config-${e.sessionId}.json`);D.default.mkdirSync(we,{recursive:!0}),D.default.writeFileSync(l,a,"utf-8");let c=`claude --dangerously-skip-permissions --mcp-config ${l}`;switch(Rs()){case"iterm2":As(c,e.projectDir,s);break;case"terminal":Es(c,e.projectDir,s);break;case"tmux":Ps(c,e.projectDir,s);break;case"direct":(0,Q.spawn)(c,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...s},stdio:"ignore",detached:!0}).unref();break}}function So(e,t,o,n,r){let s=fo().filter(a=>a.sessionId!==e);s.push({sessionId:e,pid:t,mcpPid:o,port:n,projectDir:r,startedAt:new Date().toISOString()}),ho(s)}function $o(e){let t=fo(),o=t.find(r=>r.sessionId===e);if(!o)return!1;if(o.mcpPid&&Rt(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&Rt(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,Q.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let n=t.filter(r=>r.sessionId!==e);return ho(n),!0}function vo(){let e=fo(),t=e.filter(o=>Rt(o.mcpPid)||Rt(o.pid));return t.length!==e.length&&ho(t),t}var Q,D,M,Vn,we,go,Et=L(()=>{"use strict";Q=require("child_process"),D=d(require("fs")),M=d(require("path")),Vn=d(require("os")),we=M.default.join(Vn.default.homedir(),".badgerclaw"),go=M.default.join(we,"claude-sessions.json")});async function Z(e){return e.command_type==="update_cli"?Ds(e.payload?.target_version):e.command_type==="update_plugin"?Ts(e.payload?.target_version):e.command_type==="restart_gateway"?Os():e.command_type==="leave_room"?Js(e.payload):e.command_type==="start_claude_code"?Ms(e.payload):e.command_type==="stop_claude_code"?Us(e.payload):e.command_type==="start_claude_control"?Fs(e.payload):e.command_type==="stop_claude_control"?Hs(e.payload):e.command_type==="update_claude_tools"?Gs(e.payload):e.command_type==="bot_share_notify"?Vs(e.payload):e.command_type==="bot_share_revoked"?Ws(e.payload):e.command_type==="bot_share_expired"?Ks(e.payload):e.command_type==="bot_refresh"?qs(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function Os(){try{return(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,R.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 Ds(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,R.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,R.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),r=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return Ns(),{success:!0,message:`Updated CLI to ${r}`,newVersion:r}}catch(o){let n=o.stderr?.toString()||o.message||"Unknown error";return n.includes("EACCES")||n.includes("permission")?{success:!1,message:"Permission denied. Run: sudo npm install -g badgerclaw"}:{success:!1,message:`CLI update failed: ${n.slice(0,500)}`}}}async function Ts(e){let t=$.default.join(be.default.homedir(),".openclaw","extensions","badgerclaw"),o=$.default.join(be.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),n=h.default.existsSync(o)?"npm":h.default.existsSync(t)?"legacy":null;if(n===null)return{success:!1,message:"Cannot find plugin install (checked ~/.openclaw/npm/node_modules/@badgerclaw/connect and ~/.openclaw/extensions/badgerclaw). Re-run: badgerclaw setup"};let r=e?`@badgerclaw/connect@${e}`:"@badgerclaw/connect@latest";try{if(n==="npm"){let u=$.default.dirname($.default.dirname($.default.dirname(o)));(0,R.execSync)(`npm install ${r}`,{cwd:u,stdio:"pipe",timeout:12e4});let p=$.default.join(o,"package.json"),A="unknown";h.default.existsSync(p)&&(A=JSON.parse(h.default.readFileSync(p,"utf-8")).version||"unknown"),po(A);try{(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await Wn(A)}let s=t;(0,R.execSync)(`npm install ${r}`,{cwd:s,stdio:"pipe",timeout:12e4});let a=$.default.join(s,"node_modules","@badgerclaw","connect"),l=$.default.join(a,"package.json"),c="unknown";h.default.existsSync(l)&&(c=JSON.parse(h.default.readFileSync(l,"utf-8")).version||"unknown"),po(c),Ls(a,s);let i=$.default.join(s,"package.json");if(h.default.existsSync(i)&&h.default.existsSync(l))try{let u=JSON.parse(h.default.readFileSync(i,"utf-8")),p=JSON.parse(h.default.readFileSync(l,"utf-8"));u.version=c,p.openclaw&&(u.openclaw={...u.openclaw,...p.openclaw}),h.default.writeFileSync(i,JSON.stringify(u,null,2)+`
68
- `)}catch{}try{(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await Wn(c)}catch(s){return{success:!1,message:`Plugin update failed: ${(s.stderr?.toString()||s.message||"").slice(0,500)}`}}}async function Wn(e){for(let t=0;t<15;t++){await new Promise(o=>setTimeout(o,1e3));try{let o=await T.default.get("http://localhost:7331/health",{timeout:3e3});if(o.data?.status==="running"&&o.data?.pluginVersion===e)break}catch{}}return{success:!0,message:`Updated plugin to ${e}, gateway restarted`,newVersion:e}}function Ls(e,t){let o=$.default.join(e,"dist"),n=$.default.join(t,"dist");h.default.existsSync(o)&&(h.default.mkdirSync(n,{recursive:!0}),Io(o,n));let r=$.default.join(e,"openclaw.plugin.json");h.default.existsSync(r)&&h.default.copyFileSync(r,$.default.join(t,"openclaw.plugin.json"));let s=$.default.join(e,"scripts"),a=$.default.join(t,"scripts");h.default.existsSync(s)&&(h.default.mkdirSync(a,{recursive:!0}),Io(s,a));for(let l of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let c=$.default.join(t,l);h.default.existsSync(c)&&(h.default.statSync(c).isDirectory()?h.default.rmSync(c,{recursive:!0,force:!0}):h.default.unlinkSync(c))}}function Io(e,t){for(let o of h.default.readdirSync(e,{withFileTypes:!0})){let n=$.default.join(e,o.name),r=$.default.join(t,o.name);o.isDirectory()?(h.default.mkdirSync(r,{recursive:!0}),Io(n,r)):h.default.copyFileSync(n,r)}}function Ns(){try{try{(0,R.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,R.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,R.execSync)("sleep 1",{stdio:"pipe"});let e=(0,R.execSync)("which badgerclaw",{stdio:"pipe"}).toString().trim();(0,R.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,R.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function js(){let e=$.default.join(be.default.homedir(),".badgerclaw","workspace");h.default.mkdirSync(e,{recursive:!0});let t=$.default.join(e,".git");return h.default.existsSync(t)||(0,R.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),h.default.writeFileSync($.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
67
+ `;(0,Q.execSync)(`osascript -e '${a.replace(/'/g,`'"'"'`)}'`,{stdio:"pipe",timeout:1e4})}function Os(e,t,o){let n=yo(e,o.BADGERCLAW_SESSION_ID||"default"),r=wo(o),s=`badgerclaw-${o.BADGERCLAW_SESSION_ID||"default"}`,a=`cd ${t} && ${r} && ${n}`;(0,Q.execSync)(`tmux new-session -d -s ${s} "${a}"`,{stdio:"pipe",timeout:1e4})}function At(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function bo(e){let t=M.default.join(__dirname,"..","claude-code","mcp-server.js"),o=D.default.existsSync(t)?t:M.default.join(__dirname,"mcp-server.js"),n=(0,Q.spawn)("node",[o],{env:{...process.env,BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},cwd:e.projectDir,stdio:"ignore",detached:!0});return n.unref(),n}function _o(e){let t=M.default.join(M.default.dirname(process.argv[1]||""),"..","lib","node_modules","badgerclaw","dist","claude-code","mcp-server.js"),o=M.default.join(__dirname,"..","claude-code","mcp-server.js"),n=M.default.join(__dirname,"mcp-server.js"),r=D.default.existsSync(t)?t:D.default.existsSync(o)?o:n,s={BADGERCLAW_MCP_PORT:String(e.port),BADGERCLAW_SESSION_ID:e.sessionId},a=JSON.stringify({mcpServers:{badgerclaw:{command:"node",args:[r],env:s}}}),l=M.default.join(we,`mcp-config-${e.sessionId}.json`);D.default.mkdirSync(we,{recursive:!0}),D.default.writeFileSync(l,a,"utf-8");let c=`claude --dangerously-skip-permissions --mcp-config ${l}`;switch(As()){case"iterm2":Es(c,e.projectDir,s);break;case"terminal":Ps(c,e.projectDir,s);break;case"tmux":Os(c,e.projectDir,s);break;case"direct":(0,Q.spawn)(c,[],{shell:!0,cwd:e.projectDir,env:{...process.env,...s},stdio:"ignore",detached:!0}).unref();break}}function So(e,t,o,n,r){let s=fo().filter(a=>a.sessionId!==e);s.push({sessionId:e,pid:t,mcpPid:o,port:n,projectDir:r,startedAt:new Date().toISOString()}),ho(s)}function $o(e){let t=fo(),o=t.find(r=>r.sessionId===e);if(!o)return!1;if(o.mcpPid&&Rt(o.mcpPid))try{process.kill(o.mcpPid,"SIGTERM")}catch{}if(o.pid&&Rt(o.pid))try{process.kill(o.pid,"SIGTERM")}catch{}try{(0,Q.execSync)(`tmux kill-session -t badgerclaw-${e} 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let n=t.filter(r=>r.sessionId!==e);return ho(n),!0}function vo(){let e=fo(),t=e.filter(o=>Rt(o.mcpPid)||Rt(o.pid));return t.length!==e.length&&ho(t),t}var Q,D,M,Wn,we,go,Et=L(()=>{"use strict";Q=require("child_process"),D=d(require("fs")),M=d(require("path")),Wn=d(require("os")),we=M.default.join(Wn.default.homedir(),".badgerclaw"),go=M.default.join(we,"claude-sessions.json")});async function Z(e){return e.command_type==="update_cli"?Ts(e.payload?.target_version):e.command_type==="update_plugin"?Ls(e.payload?.target_version):e.command_type==="restart_gateway"?Ds():e.command_type==="leave_room"?Ys(e.payload):e.command_type==="start_claude_code"?Us(e.payload):e.command_type==="stop_claude_code"?Fs(e.payload):e.command_type==="start_claude_control"?Hs(e.payload):e.command_type==="stop_claude_control"?Gs(e.payload):e.command_type==="update_claude_tools"?Vs(e.payload):e.command_type==="bot_share_notify"?Ws(e.payload):e.command_type==="bot_share_revoked"?Ks(e.payload):e.command_type==="bot_share_expired"?qs(e.payload):e.command_type==="bot_refresh"?Js(e.payload):{success:!1,message:`Unknown command: ${e.command_type}`}}function Ds(){try{return(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:"Gateway restarted"}}catch{try{return{success:!0,message:`Gateway restarted via probe: ${(0,R.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 Ts(e){let t=e?`badgerclaw@${e}`:"badgerclaw@latest";try{(0,R.execSync)(`npm install -g ${t}`,{stdio:"pipe",timeout:12e4});let o=(0,R.execSync)("npm list -g badgerclaw --json",{stdio:"pipe"}).toString(),r=JSON.parse(o)?.dependencies?.badgerclaw?.version||"unknown";return js(),{success:!0,message:`Updated CLI to ${r}`,newVersion:r}}catch(o){let n=o.stderr?.toString()||o.message||"Unknown error";return n.includes("EACCES")||n.includes("permission")?{success:!1,message:"Permission denied. Run: sudo npm install -g badgerclaw"}:{success:!1,message:`CLI update failed: ${n.slice(0,500)}`}}}async function Ls(e){let t=$.default.join(be.default.homedir(),".openclaw","extensions","badgerclaw"),o=$.default.join(be.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),n=h.default.existsSync(o)?"npm":h.default.existsSync(t)?"legacy":null;if(n===null)return{success:!1,message:"Cannot find plugin install (checked ~/.openclaw/npm/node_modules/@badgerclaw/connect and ~/.openclaw/extensions/badgerclaw). Re-run: badgerclaw setup"};let r=e?`@badgerclaw/connect@${e}`:"@badgerclaw/connect@latest";try{if(n==="npm"){let u=$.default.dirname($.default.dirname($.default.dirname(o)));(0,R.execSync)(`npm install ${r}`,{cwd:u,stdio:"pipe",timeout:12e4});let p=$.default.join(o,"package.json"),A="unknown";h.default.existsSync(p)&&(A=JSON.parse(h.default.readFileSync(p,"utf-8")).version||"unknown"),po(A);try{(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await Kn(A)}let s=t;(0,R.execSync)(`npm install ${r}`,{cwd:s,stdio:"pipe",timeout:12e4});let a=$.default.join(s,"node_modules","@badgerclaw","connect"),l=$.default.join(a,"package.json"),c="unknown";h.default.existsSync(l)&&(c=JSON.parse(h.default.readFileSync(l,"utf-8")).version||"unknown"),po(c),Ns(a,s);let i=$.default.join(s,"package.json");if(h.default.existsSync(i)&&h.default.existsSync(l))try{let u=JSON.parse(h.default.readFileSync(i,"utf-8")),p=JSON.parse(h.default.readFileSync(l,"utf-8"));u.version=c,p.openclaw&&(u.openclaw={...u.openclaw,...p.openclaw}),h.default.writeFileSync(i,JSON.stringify(u,null,2)+`
68
+ `)}catch{}try{(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:1e4})}catch{}return await Kn(c)}catch(s){return{success:!1,message:`Plugin update failed: ${(s.stderr?.toString()||s.message||"").slice(0,500)}`}}}async function Kn(e){for(let t=0;t<15;t++){await new Promise(o=>setTimeout(o,1e3));try{let o=await T.default.get("http://localhost:7331/health",{timeout:3e3});if(o.data?.status==="running"&&o.data?.pluginVersion===e)break}catch{}}return{success:!0,message:`Updated plugin to ${e}, gateway restarted`,newVersion:e}}function Ns(e,t){let o=$.default.join(e,"dist"),n=$.default.join(t,"dist");h.default.existsSync(o)&&(h.default.mkdirSync(n,{recursive:!0}),Io(o,n));let r=$.default.join(e,"openclaw.plugin.json");h.default.existsSync(r)&&h.default.copyFileSync(r,$.default.join(t,"openclaw.plugin.json"));let s=$.default.join(e,"scripts"),a=$.default.join(t,"scripts");h.default.existsSync(s)&&(h.default.mkdirSync(a,{recursive:!0}),Io(s,a));for(let l of["index.ts","src","STREAMING.md","SETUP.md","CHANGELOG.md"]){let c=$.default.join(t,l);h.default.existsSync(c)&&(h.default.statSync(c).isDirectory()?h.default.rmSync(c,{recursive:!0,force:!0}):h.default.unlinkSync(c))}}function Io(e,t){for(let o of h.default.readdirSync(e,{withFileTypes:!0})){let n=$.default.join(e,o.name),r=$.default.join(t,o.name);o.isDirectory()?(h.default.mkdirSync(r,{recursive:!0}),Io(n,r)):h.default.copyFileSync(n,r)}}function js(){try{try{(0,R.execSync)('pkill -f "badgerclaw heartbeat"',{stdio:"pipe",timeout:5e3})}catch{}try{(0,R.execSync)('pkill -f "badgerclaw watch"',{stdio:"pipe",timeout:5e3})}catch{}(0,R.execSync)("sleep 1",{stdio:"pipe"});let e=(0,R.execSync)("which badgerclaw",{stdio:"pipe"}).toString().trim();(0,R.execSync)(`nohup ${e} heartbeat > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"}),(0,R.execSync)(`nohup ${e} watch > /dev/null 2>&1 &`,{stdio:"pipe",shell:"/bin/zsh"})}catch{}}function Bs(){let e=$.default.join(be.default.homedir(),".badgerclaw","workspace");h.default.mkdirSync(e,{recursive:!0});let t=$.default.join(e,".git");return h.default.existsSync(t)||(0,R.execSync)("git init",{cwd:e,stdio:"pipe",timeout:5e3}),h.default.writeFileSync($.default.join(e,"CLAUDE.md"),`You are a chat assistant connected to Matrix rooms via BadgerClaw.
69
69
 
70
70
  When you receive a message, it will be formatted like:
71
71
  [Room: RoomName] Sender: message text
@@ -74,14 +74,14 @@ Reply using the reply tool with botId="..." and roomId="..."
74
74
  ALWAYS use the \`reply\` MCP tool to send your response back to the chat room.
75
75
  Use the exact botId and roomId provided in the message \u2014 do not modify them.
76
76
  Keep responses concise and helpful.
77
- `),e}function Bs(){try{h.default.mkdirSync($.default.dirname(Pt),{recursive:!0});try{let e=h.default.statSync(Pt);if(Date.now()-e.mtimeMs<6e4)return!1;h.default.unlinkSync(Pt)}catch{}return h.default.writeFileSync(Pt,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function Ms(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!Bs())return{success:!0,message:"Claude Code start already in progress, skipping duplicate"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await ze(e.bot_id),{launchClaudeCode:o,recordSession:n,getActiveSessions:r,stopSession:s}=(Et(),Po(Co)),a=new Set;try{let A=(await T.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let f of A)if(f.botId!==t&&f.enabled!==!1){let w=f.port;typeof w=="number"&&w>=7332&&a.add(w)}}catch{}for(let p=7332;p<=7340;p++)try{(0,R.execSync)(`lsof -ti :${p} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(p)}catch{}let l=7332;for(;a.has(l);)l++;let c=r();for(let p of c)p.port===l&&(console.log(`[command-executor] Stopping existing session ${p.sessionId} on port ${l}`),s(p.sessionId));try{(0,R.execSync)(`lsof -ti :${l} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let i=e.session_id||`session-${Date.now()}`;await T.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:i,port:l},{timeout:1e4});let u=js();return o({sessionId:i,port:l,projectDir:u}),n(i,0,0,l,u),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${i}, port: ${l})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function ze(e){if(e.startsWith("@"))return e;try{let o=(await T.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],n=$.default.join(be.default.homedir(),".badgerclaw","bot-mapping.json");if(h.default.existsSync(n)){let r=JSON.parse(h.default.readFileSync(n,"utf-8"));if(r[e])return r[e]}return o.length===1?o[0].botId:(console.warn(`[command-executor] Could not resolve bot UUID ${e} to Matrix ID, trying as-is`),e)}catch{return e}}async function 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 ze(e.bot_id),o=e.session_id;if(!o)try{let n=await T.default.get("http://localhost:7331/claude-code/status",{timeout:5e3}),s=(n.data?.bots||n.data?.rooms||[]).find(a=>a.botId===t);s&&(o=s.sessionId)}catch{}if(await T.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:n}=(Et(),Po(Co));n(o)}return{success:!0,message:"Claude Code stopped"}}catch(t){return{success:!1,message:`Failed to stop Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Fs(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;o.startsWith("@")||(o=await ze(t));let n=e?.session_id||`cc-${Date.now()}`;return await T.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!0,sessionId:n,mode:"primary",tools:e?.tools},{timeout:1e4}),console.log(`[claude-control] Primary mode enabled for ${o} (session: ${n})`),{success:!0,message:`Claude Control (primary) started for ${o}`}}catch(t){return{success:!1,message:`Failed to start Claude Control: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Hs(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;return o.startsWith("@")||(o=await ze(t)),await T.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 Gs(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t||!e?.tools)return{success:!1,message:"Missing bot_id or tools in payload"};let o=t;return o.startsWith("@")||(o=await ze(t)),await T.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 Vs(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 T.default.post("http://localhost:7331/bot-share/notify",{botId:e.bot_user_id,sharedWithUserId:e.shared_with_user_id,ownerDisplayName:e.owner_display_name||void 0,botDisplayName:e.bot_name||void 0,expiresAt:e.expires_at||void 0},{timeout:1e4}),console.log(`[bot-share] Notify: ${e.shared_with_user_id} can now access ${e.bot_user_id}`),{success:!0,message:`Share notification sent for ${e.shared_with_user_id}`}}catch(t){return{success:!1,message:`Failed to notify share: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Ws(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await T.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 Ks(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 T.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 qs(e){let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in bot_refresh payload"};let o=t;t.startsWith("@")&&(o=t.split(":")[0].replace("@","").replace(/_bot$/,""));let n=$.default.join(be.default.homedir(),".openclaw","badgerclaw","quarantine",`${o}.json`);try{h.default.rmSync(n,{force:!0})}catch{}try{return(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:`Bot ${o} quarantine cleared, gateway restarted`}}catch{return{success:!1,message:`Quarantine cleared for ${o} but gateway restart failed`}}}async function Js(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 T.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 R,h,$,be,T,Pt,ko=L(()=>{"use strict";R=require("child_process"),h=d(require("fs")),$=d(require("path")),be=d(require("os")),T=d(require("axios"));ye();Pt=$.default.join(be.default.homedir(),".badgerclaw","claude-code.lock")});var er={};Nt(er,{heartbeatCommand:()=>xo,pushHeartbeat:()=>O});function Dt(e,t){if(e!=="start_claude_code"&&e!=="stop_claude_code")return!1;let o=`${e}:${t||"unknown"}`,n=Date.now();for(let[r,s]of Ot)n-s>Zs&&Ot.delete(r);return Ot.has(o)?!0:(Ot.set(o,n),!1)}function Qn(e,t){let o=st();return{instance_id:K(),timestamp:new Date().toISOString(),cli_version:t,plugin_version:e.pluginVersion||"unknown",hostname:o.hostname,os:o.os,arch:o.arch,uptime_seconds:o.uptimeSeconds,mem_free_mb:o.memFreeMb,gateway_status:e.status,gateway_pid:e.pid,last_gateway_restart:e.lastRestart,capabilities:ge(),hermes_containers:ln(),bots:e.bots.map(n=>({bot_id:n.botId,bot_username:n.botUsername,status:n.status,activity_state:n.activityState||"idle",active_task:n.activeTask||null,last_activity_at:n.lastActivity,messages_received:n.messagesReceived,messages_sent:n.messagesSent,chunked_messages:n.chunkedMessages,total_chunks_sent:n.totalChunksSent,errors:n.errors,last_error:n.lastError,last_error_at:n.lastErrorAt,uptime_seconds:n.uptimeSeconds,rooms_active:n.roomsActive,room_details:(n.roomDetails||[]).map(r=>({roomId:r.roomId,roomName:r.roomName,workspaceName:r.workspaceName||null,messagesInRoom:r.messagesInRoom,lastActivityInRoom:r.lastActivityInRoom})),claude_code_enabled:n.claudeCodeEnabled??!1,claude_code_session_id:n.claudeCodeSessionId??null,quarantined:n.quarantined??!1}))}}async function O(){let{version:e}=pe(),t=await Ye(),o=Qn(t,e);await E().post(Xn,o)}function ea(e,t){if(!e||e.status!==t.status)return!0;let o=new Map(e.bots.map(n=>[n.botId,n]));for(let n of t.bots){let r=o.get(n.botId);if(!r||r.status!==n.status||r.errors!==n.errors)return!0}return e.bots.length!==t.bots.length}async function Jn(){try{let o=(await E().get(Xs)).data?.shares||[],n={shares:o.map(r=>({botUserId:r.bot_user_id,sharedWithUserId:r.shared_with_user_id,expiresAt:r.expires_at||null,shareId:r.share_id}))};await zn.default.post("http://localhost:7331/bot-share/sync",n,{timeout:1e4}),console.log(g.default.dim(` [${v()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(g.default.dim(` [${v()}] Share sync failed (non-fatal): ${e.message}`))}}async function ta(){if(!qn){qn=!0;try{await E().post(zs,{instance_id:K()},{timeout:Qs}),console.log(g.default.dim(` [${new Date().toISOString()}] Posted disconnect \u2014 dashboard will mark machine offline immediately.`))}catch(e){console.log(g.default.dim(` [${new Date().toISOString()}] Disconnect post failed (non-fatal): ${e?.message||e}`))}}}async function Zn(){let e=S();if(!e?.expires_at)return;let t=new Date(e.expires_at).getTime(),o=Date.now(),n=300*1e3;if(t-o<n)if(console.log(g.default.dim(` [${v()}] Token expires soon \u2014 refreshing proactively...`)),await Ft())console.log(g.default.green(` [${v()}] Token refreshed successfully`));else{let s=Uo()||"unknown reason";console.log(g.default.yellow(` [${v()}] Token refresh failed: ${s}`))}}function na(e,t){let o=3e3,n=3e4,r=null;async function s(){try{await Zn();let l=S()?.access_token||e,c=require("eventsource"),i=new c(`${j}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${l}`}});i.onopen=()=>{o=3e3,console.log(g.default.dim(` [${v()}] SSE connected \u2014 listening for real-time events`)),r&&clearTimeout(r),r=setTimeout(()=>{console.log(g.default.dim(` [${v()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),i.close(),s()},oa)},i.onmessage=async u=>{try{let p=JSON.parse(u.data);await ra(p)}catch{}},i.onerror=async()=>{i.close(),r&&(clearTimeout(r),r=null),console.log(g.default.dim(` [${v()}] SSE disconnected \u2014 reconnecting in ${o/1e3}s...`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}catch(a){console.log(g.default.dim(` [${v()}] SSE connection failed: ${a.message}`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}s()}function v(){return new Date().toISOString()}async function ra(e){if(e.type==="pair"){console.log(g.default.cyan(` [${v()}] Pair event: ${e.bot_name}`)),await Ue(e.pair_code,e.bot_name,e.bot_user_id,!0);try{let{execSync:t}=await import("child_process");t("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(` [${v()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await O()}catch{}}else if(e.type==="bot.delete"&&e.bot_user_id){let t=e.bot_user_id,o=t.split(":")[0].replace("@","").replace(/_bot$/,"");console.log(g.default.yellow(` [${v()}] Bot deleted: ${t}`));try{let n=await import("fs"),r=await import("path"),s=await import("os"),a=r.join(s.homedir(),".openclaw","openclaw.json");if(me(()=>{let c=JSON.parse(n.readFileSync(a,"utf-8")),i=!1;if(c.channels?.badgerclaw?.accounts?.[o]&&(delete c.channels.badgerclaw.accounts[o],i=!0),c.agents?.list){let u=c.agents.list.length;c.agents.list=c.agents.list.filter(p=>p.id!==o),c.agents.list.length!==u&&(i=!0)}return i&&n.writeFileSync(a,JSON.stringify(c,null,2)),i})){console.log(g.default.green(` [${v()}] Removed "${o}" from openclaw.json`));let{execSync:c}=await import("child_process");try{c("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(` [${v()}] Gateway restarted`))}catch{}}}catch(n){console.log(g.default.red(` [${v()}] Failed to clean up bot: ${n}`))}try{await O()}catch{}}else if(e.type==="gateway-restart"){console.log(g.default.cyan(` [${v()}] Remote gateway-restart received`));let t=await Ae();console.log(t.success?g.default.green(` [${v()}] Gateway restarted`):g.default.red(` [${v()}] Gateway restart failed: ${t.message}`));try{await O()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(g.default.cyan(` [${v()}] Claude Code START: bot=${e.bot_id}`)),Dt("start_claude_code",e.bot_id)){console.log(g.default.dim(` [${v()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await Z({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 E().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await O()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(g.default.cyan(` [${v()}] Claude Code STOP: bot=${e.bot_id}`)),Dt("stop_claude_code",e.bot_id)){console.log(g.default.dim(` [${v()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await Z({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 E().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await O()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(g.default.cyan(` [${v()}] Command: ${e.command_type} (${e.command_id})`)),Dt(e.command_type,e.payload?.bot_id)){console.log(g.default.dim(` [${v()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=E();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await Z({id:e.command_id,command_type:e.command_type,payload:e.payload});await t.post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:o.success?"success":"failed",result:o.message,new_version:o.newVersion||null}),e.command_type==="update_cli"&&o.success&&(console.log(g.default.cyan(` [${v()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await O()}catch{}}}var Yn,g,zn,Kn,Ys,Xn,zs,Xs,Qs,qn,Ot,Zs,xo,oa,Xe=L(()=>{"use strict";Yn=require("commander"),g=d(require("chalk")),zn=d(require("axios"));N();de();$e();fe();eo();ye();ko();ne();He();ye();je();Ce();Kn=3e4,Ys=15e4,Xn="/api/v1/dashboard/heartbeat",zs="/api/v1/dashboard/disconnect",Xs="/api/v1/me/active-shares",Qs=3e3,qn=!1,Ot=new Map,Zs=3e4;xo=new Yn.Command("heartbeat").description("Run heartbeat daemon \u2014 reports telemetry to the BadgerClaw dashboard every 30s").action(async()=>{let e=S();e||(console.log(g.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=pe();console.log(g.default.green(`Heartbeat daemon started (v${t})`)),console.log(g.default.dim(` Instance: ${K()}`)),console.log(g.default.dim(` Interval: ${Kn/1e3}s`)),console.log(g.default.dim(` Press Ctrl+C to stop.
78
- `));let o=null,n=10,r=0,s=async()=>{try{await Zn();let c=await Ye(),i=Qn(c,t);ea(o,c)&&o!==null&&console.log(g.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let p=E(),A=await p.post(Xn,i);r=0;let f=c.bots.length,w=c.bots.filter(C=>C.status==="running").length;console.log(g.default.dim(` [${new Date().toISOString()}] gateway=${c.status} bots=${w}/${f} running mem=${i.mem_free_mb}MB free`)),o=c;try{let k=await dn({api:{post:async(V,Pe)=>{let et=await p.post(V,Pe);return{status:et.status,data:et.data}}}});for(let V of k)V.attempted&&(V.posted||V.envUpdated)&&console.log(g.default.cyan(` [${new Date().toISOString()}] Hermes recovery key captured for ${V.bot_id} (posted=${V.posted}, env_updated=${V.envUpdated})`))}catch(C){console.log(g.default.dim(` [${new Date().toISOString()}] Hermes recovery-key retry skipped: ${C.message}`))}let B=A.data?.pending_commands||[],oe=!1;for(let C of B)try{if(console.log(g.default.cyan(` [${new Date().toISOString()}] Received command: ${C.command_type} (${C.id})`)),await p.post(`/api/v1/dashboard/commands/${C.id}/ack`),Dt(C.command_type,C.payload?.bot_id)){console.log(g.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${C.command_type}`));continue}let k=await Z(C);console.log(k.success?g.default.green(` [${new Date().toISOString()}] ${k.message}`):g.default.red(` [${new Date().toISOString()}] ${k.message}`)),await p.post(`/api/v1/dashboard/commands/${C.id}/result`,{status:k.success?"success":"failed",result:k.message,new_version:k.newVersion||null}),C.command_type==="update_cli"&&k.success&&(oe=!0)}catch(k){console.log(g.default.dim(` [${new Date().toISOString()}] Command ${C.id} error: ${k.message}`))}if(oe){console.log(g.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await O()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(c){c instanceof ve&&(console.log(g.default.yellow(` [${new Date().toISOString()}] Account deactivated \u2014 signed out. Exiting daemon.`)),process.exit(0)),r+=1,console.log(g.default.dim(` [${new Date().toISOString()}] Heartbeat failed (${r}/${n}): ${c.message}`)),r>=n&&(console.log(g.default.red(` [${new Date().toISOString()}] ${n} consecutive heartbeat failures \u2014 exiting so launchctl/systemd can restart the daemon.`)),process.exit(1))}};await s();let a=U()!==null;a?await Jn():console.log(g.default.dim(` [${v()}] Hermes-only host \u2014 share-sync disabled (no plugin to push to).`)),setInterval(s,Kn),a&&setInterval(Jn,Ys),na(e.access_token,t);let l=c=>{console.log(g.default.yellow(`
79
- [${new Date().toISOString()}] Received ${c} \u2014 posting disconnect and exiting.`)),ta().finally(()=>{process.exit(0)})};process.on("SIGTERM",l),process.on("SIGINT",l),await new Promise(()=>{})});oa=2700*1e3});var br=require("commander");var Cn=require("commander"),X=d(require("chalk")),In=d(require("ora")),kn=d(require("open")),io=d(require("os"));var jt=d(require("crypto"));function Oo(){return jt.default.randomBytes(32).toString("base64url")}function Do(e){return jt.default.createHash("sha256").update(e).digest("base64url")}N();$e();de();ne();He();var _n=d(require("os"));var ht=d(require("fs")),he=d(require("path")),Ge=d(require("os")),Ve=require("child_process"),fn="ai.badgerclaw.watch",hn=he.default.join(Ge.default.homedir(),"Library","LaunchAgents"),ro=he.default.join(hn,`${fn}.plist`);function rs(){try{return(0,Ve.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function ss(){try{return(0,Ve.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function as(e){let t=he.default.join(Ge.default.homedir(),".badgerclaw"),o=ss(),n=he.default.dirname(o),r=he.default.dirname(e),s=[n,r,"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"],a=new Set,l=s.filter(c=>!c||a.has(c)?!1:(a.add(c),!0)).join(":");return`<?xml version="1.0" encoding="UTF-8"?>
77
+ `),e}function Ms(){try{h.default.mkdirSync($.default.dirname(Pt),{recursive:!0});try{let e=h.default.statSync(Pt);if(Date.now()-e.mtimeMs<6e4)return!1;h.default.unlinkSync(Pt)}catch{}return h.default.writeFileSync(Pt,String(process.pid),{flag:"wx"}),!0}catch{return!1}}async function Us(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};if(!Ms())return{success:!0,message:"Claude Code start already in progress, skipping duplicate"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await ze(e.bot_id),{launchClaudeCode:o,recordSession:n,getActiveSessions:r,stopSession:s}=(Et(),Po(Co)),a=new Set;try{let A=(await T.default.get("http://localhost:7331/claude-code/status",{timeout:5e3})).data?.bots||[];for(let f of A)if(f.botId!==t&&f.enabled!==!1){let w=f.port;typeof w=="number"&&w>=7332&&a.add(w)}}catch{}for(let p=7332;p<=7340;p++)try{(0,R.execSync)(`lsof -ti :${p} >/dev/null 2>&1`,{stdio:"pipe",timeout:2e3}),a.add(p)}catch{}let l=7332;for(;a.has(l);)l++;let c=r();for(let p of c)p.port===l&&(console.log(`[command-executor] Stopping existing session ${p.sessionId} on port ${l}`),s(p.sessionId));try{(0,R.execSync)(`lsof -ti :${l} | xargs kill -9 2>/dev/null`,{stdio:"pipe",timeout:3e3})}catch{}let i=e.session_id||`session-${Date.now()}`;await T.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!0,sessionId:i,port:l},{timeout:1e4});let u=Bs();return o({sessionId:i,port:l,projectDir:u}),n(i,0,0,l,u),{success:!0,message:`Claude Code started globally for bot ${t} (session: ${i}, port: ${l})`}}catch(t){return{success:!1,message:`Failed to start Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function ze(e){if(e.startsWith("@"))return e;try{let o=(await T.default.get("http://localhost:7331/health",{timeout:1e4})).data?.bots||[],n=$.default.join(be.default.homedir(),".badgerclaw","bot-mapping.json");if(h.default.existsSync(n)){let r=JSON.parse(h.default.readFileSync(n,"utf-8"));if(r[e])return r[e]}return o.length===1?o[0].botId:(console.warn(`[command-executor] Could not resolve bot UUID ${e} to Matrix ID, trying as-is`),e)}catch{return e}}async function Fs(e){if(!e?.bot_id)return{success:!1,message:"Missing bot_id in payload"};try{let t=e.bot_user_id?.startsWith("@")?e.bot_user_id:await ze(e.bot_id),o=e.session_id;if(!o)try{let n=await T.default.get("http://localhost:7331/claude-code/status",{timeout:5e3}),s=(n.data?.bots||n.data?.rooms||[]).find(a=>a.botId===t);s&&(o=s.sessionId)}catch{}if(await T.default.post("http://localhost:7331/claude-code/toggle",{botId:t,enabled:!1},{timeout:1e4}),o){let{stopSession:n}=(Et(),Po(Co));n(o)}return{success:!0,message:"Claude Code stopped"}}catch(t){return{success:!1,message:`Failed to stop Claude Code: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function Hs(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in payload"};let o=t;o.startsWith("@")||(o=await ze(t));let n=e?.session_id||`cc-${Date.now()}`;return await T.default.post("http://localhost:7331/claude-code/toggle",{botId:o,enabled:!0,sessionId:n,mode:"primary",tools:e?.tools},{timeout:1e4}),console.log(`[claude-control] Primary mode enabled for ${o} (session: ${n})`),{success:!0,message:`Claude Control (primary) started for ${o}`}}catch(t){return{success:!1,message:`Failed to start Claude Control: ${t.response?.data?.message||t.message||"Unknown error"}`}}}async function 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 ze(t)),await T.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 Vs(e){try{let t=e?.bot_user_id||e?.bot_id;if(!t||!e?.tools)return{success:!1,message:"Missing bot_id or tools in payload"};let o=t;return o.startsWith("@")||(o=await ze(t)),await T.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 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 T.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 Ks(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 T.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 qs(e){if(!e?.bot_user_id||!e?.shared_with_user_id)return{success:!1,message:"Missing bot_user_id or shared_with_user_id"};try{return await T.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 Js(e){let t=e?.bot_user_id||e?.bot_id;if(!t)return{success:!1,message:"Missing bot_id in bot_refresh payload"};let o=t;t.startsWith("@")&&(o=t.split(":")[0].replace("@","").replace(/_bot$/,""));let n=$.default.join(be.default.homedir(),".openclaw","badgerclaw","quarantine",`${o}.json`);try{h.default.rmSync(n,{force:!0})}catch{}try{return(0,R.execSync)("openclaw gateway restart",{stdio:"pipe",timeout:15e3}),{success:!0,message:`Bot ${o} quarantine cleared, gateway restarted`}}catch{return{success:!1,message:`Quarantine cleared for ${o} but gateway restart failed`}}}async function 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 T.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 R,h,$,be,T,Pt,ko=L(()=>{"use strict";R=require("child_process"),h=d(require("fs")),$=d(require("path")),be=d(require("os")),T=d(require("axios"));ye();Pt=$.default.join(be.default.homedir(),".badgerclaw","claude-code.lock")});var tr={};Nt(tr,{heartbeatCommand:()=>xo,pushHeartbeat:()=>O});function Dt(e,t){if(e!=="start_claude_code"&&e!=="stop_claude_code")return!1;let o=`${e}:${t||"unknown"}`,n=Date.now();for(let[r,s]of Ot)n-s>ea&&Ot.delete(r);return Ot.has(o)?!0:(Ot.set(o,n),!1)}function Zn(e,t){let o=st();return{instance_id:K(),timestamp:new Date().toISOString(),cli_version:t,plugin_version:e.pluginVersion||"unknown",hostname:o.hostname,os:o.os,arch:o.arch,uptime_seconds:o.uptimeSeconds,mem_free_mb:o.memFreeMb,gateway_status:e.status,gateway_pid:e.pid,last_gateway_restart:e.lastRestart,capabilities:ge(),hermes_containers:dn(),bots:e.bots.map(n=>({bot_id:n.botId,bot_username:n.botUsername,status:n.status,activity_state:n.activityState||"idle",active_task:n.activeTask||null,last_activity_at:n.lastActivity,messages_received:n.messagesReceived,messages_sent:n.messagesSent,chunked_messages:n.chunkedMessages,total_chunks_sent:n.totalChunksSent,errors:n.errors,last_error:n.lastError,last_error_at:n.lastErrorAt,uptime_seconds:n.uptimeSeconds,rooms_active:n.roomsActive,room_details:(n.roomDetails||[]).map(r=>({roomId:r.roomId,roomName:r.roomName,workspaceName:r.workspaceName||null,messagesInRoom:r.messagesInRoom,lastActivityInRoom:r.lastActivityInRoom})),claude_code_enabled:n.claudeCodeEnabled??!1,claude_code_session_id:n.claudeCodeSessionId??null,quarantined:n.quarantined??!1}))}}async function O(){let{version:e}=pe(),t=await Ye(),o=Zn(t,e);await E().post(Qn,o)}function ta(e,t){if(!e||e.status!==t.status)return!0;let o=new Map(e.bots.map(n=>[n.botId,n]));for(let n of t.bots){let r=o.get(n.botId);if(!r||r.status!==n.status||r.errors!==n.errors)return!0}return e.bots.length!==t.bots.length}async function Yn(){try{let o=(await E().get(Qs)).data?.shares||[],n={shares:o.map(r=>({botUserId:r.bot_user_id,sharedWithUserId:r.shared_with_user_id,expiresAt:r.expires_at||null,shareId:r.share_id}))};await Xn.default.post("http://localhost:7331/bot-share/sync",n,{timeout:1e4}),console.log(g.default.dim(` [${v()}] Share sync: ${o.length} active share(s) pushed to plugin`))}catch(e){console.log(g.default.dim(` [${v()}] Share sync failed (non-fatal): ${e.message}`))}}async function oa(){if(!Jn){Jn=!0;try{await E().post(Xs,{instance_id:K()},{timeout:Zs}),console.log(g.default.dim(` [${new Date().toISOString()}] Posted disconnect \u2014 dashboard will mark machine offline immediately.`))}catch(e){console.log(g.default.dim(` [${new Date().toISOString()}] Disconnect post failed (non-fatal): ${e?.message||e}`))}}}async function er(){let e=S();if(!e?.expires_at)return;let t=new Date(e.expires_at).getTime(),o=Date.now(),n=300*1e3;if(t-o<n)if(console.log(g.default.dim(` [${v()}] Token expires soon \u2014 refreshing proactively...`)),await Ft())console.log(g.default.green(` [${v()}] Token refreshed successfully`));else{let s=Uo()||"unknown reason";console.log(g.default.yellow(` [${v()}] Token refresh failed: ${s}`))}}function ra(e,t){let o=3e3,n=3e4,r=null;async function s(){try{await er();let l=S()?.access_token||e,c=require("eventsource"),i=new c(`${j}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${l}`}});i.onopen=()=>{o=3e3,console.log(g.default.dim(` [${v()}] SSE connected \u2014 listening for real-time events`)),r&&clearTimeout(r),r=setTimeout(()=>{console.log(g.default.dim(` [${v()}] SSE proactive reconnect \u2014 refreshing token before expiry`)),i.close(),s()},na)},i.onmessage=async u=>{try{let p=JSON.parse(u.data);await sa(p)}catch{}},i.onerror=async()=>{i.close(),r&&(clearTimeout(r),r=null),console.log(g.default.dim(` [${v()}] SSE disconnected \u2014 reconnecting in ${o/1e3}s...`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}catch(a){console.log(g.default.dim(` [${v()}] SSE connection failed: ${a.message}`)),setTimeout(s,o),o=Math.min(o*1.5,n)}}s()}function v(){return new Date().toISOString()}async function sa(e){if(e.type==="pair"){console.log(g.default.cyan(` [${v()}] Pair event: ${e.bot_name}`)),await Ue(e.pair_code,e.bot_name,e.bot_user_id,!0);try{let{execSync:t}=await import("child_process");t("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(` [${v()}] Gateway restarted \u2014 ${e.bot_name} is live`))}catch{}try{await O()}catch{}}else if(e.type==="bot.delete"&&e.bot_user_id){let t=e.bot_user_id,o=t.split(":")[0].replace("@","").replace(/_bot$/,"");console.log(g.default.yellow(` [${v()}] Bot deleted: ${t}`));try{let n=await import("fs"),r=await import("path"),s=await import("os"),a=r.join(s.homedir(),".openclaw","openclaw.json");if(me(()=>{let c=JSON.parse(n.readFileSync(a,"utf-8")),i=!1;if(c.channels?.badgerclaw?.accounts?.[o]&&(delete c.channels.badgerclaw.accounts[o],i=!0),c.agents?.list){let u=c.agents.list.length;c.agents.list=c.agents.list.filter(p=>p.id!==o),c.agents.list.length!==u&&(i=!0)}return i&&n.writeFileSync(a,JSON.stringify(c,null,2)),i})){console.log(g.default.green(` [${v()}] Removed "${o}" from openclaw.json`));let{execSync:c}=await import("child_process");try{c("openclaw gateway restart",{stdio:"ignore"}),console.log(g.default.green(` [${v()}] Gateway restarted`))}catch{}}}catch(n){console.log(g.default.red(` [${v()}] Failed to clean up bot: ${n}`))}try{await O()}catch{}}else if(e.type==="gateway-restart"){console.log(g.default.cyan(` [${v()}] Remote gateway-restart received`));let t=await Ae();console.log(t.success?g.default.green(` [${v()}] Gateway restarted`):g.default.red(` [${v()}] Gateway restart failed: ${t.message}`));try{await O()}catch{}}else if(e.type==="claude_code.start"&&e.bot_id){if(console.log(g.default.cyan(` [${v()}] Claude Code START: bot=${e.bot_id}`)),Dt("start_claude_code",e.bot_id)){console.log(g.default.dim(` [${v()}] Skipping duplicate start_claude_code (already processed)`));return}try{let t=await Z({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 E().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await O()}catch{}}else if(e.type==="claude_code.stop"&&e.bot_id){if(console.log(g.default.cyan(` [${v()}] Claude Code STOP: bot=${e.bot_id}`)),Dt("stop_claude_code",e.bot_id)){console.log(g.default.dim(` [${v()}] Skipping duplicate stop_claude_code (already processed)`));return}try{let t=await Z({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 E().post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:t.success?"success":"failed",result:t.message}).catch(()=>{})}catch{}try{await O()}catch{}}else if(e.type==="command.execute"&&e.command_id){if(console.log(g.default.cyan(` [${v()}] Command: ${e.command_type} (${e.command_id})`)),Dt(e.command_type,e.payload?.bot_id)){console.log(g.default.dim(` [${v()}] Skipping duplicate ${e.command_type} (already processed)`));return}try{let t=E();await t.post(`/api/v1/dashboard/commands/${e.command_id}/ack`);let o=await Z({id:e.command_id,command_type:e.command_type,payload:e.payload});await t.post(`/api/v1/dashboard/commands/${e.command_id}/result`,{status:o.success?"success":"failed",result:o.message,new_version:o.newVersion||null}),e.command_type==="update_cli"&&o.success&&(console.log(g.default.cyan(` [${v()}] CLI updated \u2014 restarting in 2s...`)),setTimeout(()=>process.exit(0),2e3))}catch{}try{await O()}catch{}}}var zn,g,Xn,qn,zs,Qn,Xs,Qs,Zs,Jn,Ot,ea,xo,na,Xe=L(()=>{"use strict";zn=require("commander"),g=d(require("chalk")),Xn=d(require("axios"));N();de();$e();fe();eo();ye();ko();ne();He();ye();je();Ce();qn=3e4,zs=15e4,Qn="/api/v1/dashboard/heartbeat",Xs="/api/v1/dashboard/disconnect",Qs="/api/v1/me/active-shares",Zs=3e3,Jn=!1,Ot=new Map,ea=3e4;xo=new zn.Command("heartbeat").description("Run heartbeat daemon \u2014 reports telemetry to the BadgerClaw dashboard every 30s").action(async()=>{let e=S();e||(console.log(g.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=pe();console.log(g.default.green(`Heartbeat daemon started (v${t})`)),console.log(g.default.dim(` Instance: ${K()}`)),console.log(g.default.dim(` Interval: ${qn/1e3}s`)),console.log(g.default.dim(` Press Ctrl+C to stop.
78
+ `));let o=null,n=10,r=0,s=async()=>{try{await er();let c=await Ye(),i=Zn(c,t);ta(o,c)&&o!==null&&console.log(g.default.cyan(` [${new Date().toISOString()}] State change detected \u2014 pushing immediately`));let p=E(),A=await p.post(Qn,i);r=0;let f=c.bots.length,w=c.bots.filter(C=>C.status==="running").length;console.log(g.default.dim(` [${new Date().toISOString()}] gateway=${c.status} bots=${w}/${f} running mem=${i.mem_free_mb}MB free`)),o=c;try{let k=await un({api:{post:async(V,Pe)=>{let et=await p.post(V,Pe);return{status:et.status,data:et.data}}}});for(let V of k)V.attempted&&(V.posted||V.envUpdated)&&console.log(g.default.cyan(` [${new Date().toISOString()}] Hermes recovery key captured for ${V.bot_id} (posted=${V.posted}, env_updated=${V.envUpdated})`))}catch(C){console.log(g.default.dim(` [${new Date().toISOString()}] Hermes recovery-key retry skipped: ${C.message}`))}let B=A.data?.pending_commands||[],oe=!1;for(let C of B)try{if(console.log(g.default.cyan(` [${new Date().toISOString()}] Received command: ${C.command_type} (${C.id})`)),await p.post(`/api/v1/dashboard/commands/${C.id}/ack`),Dt(C.command_type,C.payload?.bot_id)){console.log(g.default.dim(` [${new Date().toISOString()}] Skipping duplicate ${C.command_type}`));continue}let k=await Z(C);console.log(k.success?g.default.green(` [${new Date().toISOString()}] ${k.message}`):g.default.red(` [${new Date().toISOString()}] ${k.message}`)),await p.post(`/api/v1/dashboard/commands/${C.id}/result`,{status:k.success?"success":"failed",result:k.message,new_version:k.newVersion||null}),C.command_type==="update_cli"&&k.success&&(oe=!0)}catch(k){console.log(g.default.dim(` [${new Date().toISOString()}] Command ${C.id} error: ${k.message}`))}if(oe){console.log(g.default.cyan(` [${new Date().toISOString()}] CLI updated \u2014 restarting in 2s...`));try{await O()}catch{}setTimeout(()=>process.exit(0),2e3);return}}catch(c){c instanceof ve&&(console.log(g.default.yellow(` [${new Date().toISOString()}] Account deactivated \u2014 signed out. Exiting daemon.`)),process.exit(0)),r+=1,console.log(g.default.dim(` [${new Date().toISOString()}] Heartbeat failed (${r}/${n}): ${c.message}`)),r>=n&&(console.log(g.default.red(` [${new Date().toISOString()}] ${n} consecutive heartbeat failures \u2014 exiting so launchctl/systemd can restart the daemon.`)),process.exit(1))}};await s();let a=U()!==null;a?await Yn():console.log(g.default.dim(` [${v()}] Hermes-only host \u2014 share-sync disabled (no plugin to push to).`)),setInterval(s,qn),a&&setInterval(Yn,zs),ra(e.access_token,t);let l=c=>{console.log(g.default.yellow(`
79
+ [${new Date().toISOString()}] Received ${c} \u2014 posting disconnect and exiting.`)),oa().finally(()=>{process.exit(0)})};process.on("SIGTERM",l),process.on("SIGINT",l),await new Promise(()=>{})});na=2700*1e3});var _r=require("commander");var In=require("commander"),X=d(require("chalk")),kn=d(require("ora")),xn=d(require("open")),io=d(require("os"));var jt=d(require("crypto"));function Oo(){return jt.default.randomBytes(32).toString("base64url")}function Do(e){return jt.default.createHash("sha256").update(e).digest("base64url")}N();$e();de();ne();He();var Sn=d(require("os"));var ht=d(require("fs")),he=d(require("path")),Ge=d(require("os")),Ve=require("child_process"),hn="ai.badgerclaw.watch",yn=he.default.join(Ge.default.homedir(),"Library","LaunchAgents"),ro=he.default.join(yn,`${hn}.plist`);function ss(){try{return(0,Ve.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/badgerclaw"}}function as(){try{return(0,Ve.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/opt/homebrew/bin/node"}}function is(e){let t=he.default.join(Ge.default.homedir(),".badgerclaw"),o=as(),n=he.default.dirname(o),r=he.default.dirname(e),s=[n,r,"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"],a=new Set,l=s.filter(c=>!c||a.has(c)?!1:(a.add(c),!0)).join(":");return`<?xml version="1.0" encoding="UTF-8"?>
80
80
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
81
81
  <plist version="1.0">
82
82
  <dict>
83
83
  <key>Label</key>
84
- <string>${fn}</string>
84
+ <string>${hn}</string>
85
85
  <key>ProgramArguments</key>
86
86
  <array>
87
87
  <string>${o}</string>
@@ -104,7 +104,7 @@ Keep responses concise and helpful.
104
104
  <key>ThrottleInterval</key>
105
105
  <integer>30</integer>
106
106
  </dict>
107
- </plist>`}function yn(){if(Ge.default.platform()==="darwin")try{let e=rs();ht.default.mkdirSync(hn,{recursive:!0}),ht.default.mkdirSync(he.default.join(Ge.default.homedir(),".badgerclaw"),{recursive:!0}),ht.default.writeFileSync(ro,as(e));try{(0,Ve.execSync)(`launchctl unload "${ro}" 2>/dev/null`)}catch{}(0,Ve.execSync)(`launchctl load "${ro}"`),console.log("\x1B[2mPair-watcher registered as background service (auto-starts on login).\x1B[0m")}catch{console.log("\x1B[2mNote: could not register background service. Run `badgerclaw watch` manually.\x1B[0m")}}var yt=d(require("fs")),We=d(require("path")),wt=d(require("os")),z=require("child_process"),so="badgerclaw-watch.service",wn=We.default.join(wt.default.homedir(),".config","systemd","user"),is=We.default.join(wn,so);function cs(){try{return(0,z.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function ls(){try{return(0,z.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function ds(e){let t=ls(),o=We.default.dirname(t);return`[Unit]
107
+ </plist>`}function wn(){if(Ge.default.platform()==="darwin")try{let e=ss();ht.default.mkdirSync(yn,{recursive:!0}),ht.default.mkdirSync(he.default.join(Ge.default.homedir(),".badgerclaw"),{recursive:!0}),ht.default.writeFileSync(ro,is(e));try{(0,Ve.execSync)(`launchctl unload "${ro}" 2>/dev/null`)}catch{}(0,Ve.execSync)(`launchctl load "${ro}"`),console.log("\x1B[2mPair-watcher registered as background service (auto-starts on login).\x1B[0m")}catch{console.log("\x1B[2mNote: could not register background service. Run `badgerclaw watch` manually.\x1B[0m")}}var yt=d(require("fs")),We=d(require("path")),wt=d(require("os")),z=require("child_process"),so="badgerclaw-watch.service",bn=We.default.join(wt.default.homedir(),".config","systemd","user"),cs=We.default.join(bn,so);function ls(){try{return(0,z.execSync)("which badgerclaw",{encoding:"utf-8"}).trim()}catch{return"/usr/local/bin/badgerclaw"}}function ds(){try{return(0,z.execSync)("which node",{encoding:"utf-8"}).trim()}catch{return"/usr/bin/node"}}function us(e){let t=ds(),o=We.default.dirname(t);return`[Unit]
108
108
  Description=BadgerClaw background watcher (heartbeat + pair events)
109
109
  After=network-online.target
110
110
  Wants=network-online.target
@@ -120,38 +120,38 @@ StandardError=append:%h/.badgerclaw/heartbeat.log
120
120
 
121
121
  [Install]
122
122
  WantedBy=default.target
123
- `}function us(){try{return(0,z.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function bn(){if(wt.default.platform()==="linux"){if(!us()){console.log("\x1B[2mNote: systemctl --user not available. Run `badgerclaw heartbeat` manually or start it under a process manager.\x1B[0m");return}try{let e=cs();yt.default.mkdirSync(wn,{recursive:!0}),yt.default.mkdirSync(We.default.join(wt.default.homedir(),".badgerclaw"),{recursive:!0}),yt.default.writeFileSync(is,ds(e)),(0,z.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,z.execSync)(`systemctl --user restart ${so}`,{stdio:"ignore"})}catch{}(0,z.execSync)(`systemctl --user enable --now ${so}`,{stdio:"ignore"});try{let t=(0,z.execSync)("whoami",{encoding:"utf-8"}).trim();(0,z.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 Sn(){let e=_n.default.platform();if(e==="darwin")return yn();if(e==="linux")return bn();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var ie=d(require("fs")),ao=d(require("os")),bt=d(require("path")),J=require("child_process"),H=d(require("chalk"));je();var $n=bt.default.join(ao.default.homedir(),".openclaw","openclaw.json");function ms(){return process.platform!=="linux"?!1:!!(ie.default.existsSync("/.dockerenv")||(0,J.spawnSync)("which",["systemctl"],{encoding:"utf-8"}).status!==0)}function vn(e=!1){let t=null;try{ie.default.existsSync($n)&&(t=JSON.parse(ie.default.readFileSync($n,"utf-8"))?.gateway?.mode??null)}catch{}if(typeof t=="string"&&t.length>0)return!0;e||console.log(H.default.dim(" Setting gateway.mode=local..."));try{return me(()=>((0,J.execSync)("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),!0))}catch(o){return e||(console.log(H.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${o.message}`)),console.log(H.default.yellow(" Run `openclaw config set gateway.mode local` manually."))),!1}}function _t(e={}){let t=e.verbose!==!1,o=a=>{t&&console.log(a)};if(ms())return ps(t);o(H.default.dim(" Installing OpenClaw gateway service (if not present)...")),(0,J.spawnSync)("openclaw",["gateway","install"],{stdio:t?"inherit":"pipe",shell:!0}).status!==0&&o(H.default.yellow(" \u26A0\uFE0F `openclaw gateway install` returned non-zero \u2014 continuing.")),vn(!t),o(H.default.dim(" Starting OpenClaw gateway..."));let r=(0,J.spawnSync)("openclaw",["gateway","start"],{stdio:t?"inherit":"pipe",shell:!0}),s="started";return r.status!==0&&(r=(0,J.spawnSync)("openclaw",["gateway","restart"],{stdio:t?"inherit":"pipe",shell:!0}),s="restarted"),r.status!==0?{ok:!1,error:"gateway start/restart returned non-zero exit"}:{ok:!0,state:s}}function ps(e){let t=i=>{e&&console.log(i)};t(H.default.dim(" Container mode (no systemd) \u2014 running gateway in foreground via nohup.")),vn(!e);let o=bt.default.join(ao.default.homedir(),".openclaw","logs");try{ie.default.mkdirSync(o,{recursive:!0})}catch{}let n=bt.default.join(o,"gateway-foreground.log"),r,s;try{r=ie.default.openSync(n,"a"),s=ie.default.openSync(n,"a")}catch(i){return{ok:!1,error:`cannot open gateway log at ${n}: ${i.message}`}}let a=(0,J.spawn)("openclaw",["gateway"],{detached:!0,stdio:["ignore",r,s]});if(a.pid==null)return{ok:!1,error:"failed to spawn `openclaw gateway`"};a.unref(),t(H.default.dim(` Gateway PID: ${a.pid}, log: ${n}`));let l=Date.now()+2e4,c=!1;for(;Date.now()<l;){try{let u=ie.default.readFileSync(n,"utf-8");if(u.includes("[gateway] ready")){c=!0;break}if(/EADDRINUSE|FATAL|Error:|gateway start blocked/.test(u))return{ok:!1,error:`gateway aborted on startup \u2014 see ${n}`}}catch{}let i=new SharedArrayBuffer(4);Atomics.wait(new Int32Array(i),0,0,200)}return c?{ok:!0,state:"started"}:{ok:!1,error:`gateway did not report ready within 20s \u2014 see ${n}`}}function St(){if(process.platform!=="linux"||process.getuid?.()!==0)return;let e=(0,J.spawnSync)("loginctl",["show-user","root","--property=Linger"],{encoding:"utf-8"});e.status===0&&/Linger=no/.test(e.stdout||"")&&(console.log(H.default.yellow(`
124
- \u26A0\uFE0F systemd lingering is OFF for root. The gateway will stop on SSH disconnect.`)),console.log(H.default.dim(" Enable persistence: loginctl enable-linger root")))}Ce();var gs=2e3,fs=12e4,xn=new Cn.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=Oo(),t=Do(e),o=`${Bo}/cli-auth?code=${t}`;console.log(X.default.yellow("Opening browser for authentication...")),console.log(X.default.dim(`If the browser doesn't open, visit: ${o}`)),await(0,kn.default)(o);let n=(0,In.default)("Waiting for authentication...").start(),r=Go(),s=Date.now();for(;Date.now()-s<fs;){try{let a=await r.post(`/api/v1/openclaw/cli/auth/poll/${t}`,{code_verifier:e,code_challenge:t});if(a.status===429){await new Promise(l=>setTimeout(l,5e3));continue}if(a.data?.access_token){let{access_token:l,user_id:c,expires_at:i,refresh_token:u,email:p}=a.data,A=Ut(),f=`openclaw-${io.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${A}`,w=f;try{let{version:oe}=pe(),C=await r.post("/api/v1/openclaw/register",{instance_id:f,label:io.default.hostname(),version:oe,machine_fingerprint:A},{headers:{Authorization:`Bearer ${l}`}}),k=C.data?.result||C.data;k&&typeof k.instance_id=="string"&&k.instance_id.length>0&&(w=k.instance_id)}catch(oe){let C=oe?.response?.status;if(C===403||C===409){let k=oe?.response?.data,V=Array.isArray(k?.errors)&&typeof k.errors[0]=="string"?k.errors[0]:null,Pe=k?.detail,et=typeof Pe=="string"?Pe:Pe?.error==="downgrade_selection_required"?"Your account has an unresolved plan-change request. Open the BadgerClaw app to finish the downgrade selection, then try again.":null,_r=V||et||`Login refused (status ${C}). Open the BadgerClaw app to check your subscription state.`;n.fail(X.default.red(_r)),process.exit(1)}}ot({access_token:l,user_id:c,instance_id:w,expires_at:i,refresh_token:u,email:p}),n.succeed(X.default.green(`Logged in as ${rt(c)}`)),U()!==null?_t({verbose:!0}).ok||console.log(X.default.yellow("\n \u26A0\uFE0F Logged in, but gateway failed to start. Re-run `badgerclaw setup` to repair.")):console.log(X.default.dim(" Hermes-only host \u2014 skipping OpenClaw gateway bring-up."));let B=await Fe(!0);B>0&&console.log(X.default.green(`\u2705 ${B} bot(s) automatically paired to OpenClaw.`)),Sn(),St();return}}catch{}await new Promise(a=>setTimeout(a,gs))}n.fail(X.default.red("Authentication timed out. Please try again.")),process.exit(1)});var An=require("commander"),Ke=d(require("chalk")),$t=d(require("fs")),ke=d(require("os")),Je=d(require("path")),qe=require("child_process");N();de();function hs(){let e=process.platform;if(e==="darwin"){let t=Je.default.join(ke.default.homedir(),"Library","LaunchAgents","ai.badgerclaw.watch.plist");(0,qe.spawnSync)("launchctl",["unload",t],{stdio:"ignore"});try{$t.default.unlinkSync(t)}catch{}}else if(e==="linux"){(0,qe.spawnSync)("systemctl",["--user","disable","--now","badgerclaw-watch.service"],{stdio:"ignore"});let t=Je.default.join(ke.default.homedir(),".config","systemd","user","badgerclaw-watch.service");try{$t.default.unlinkSync(t)}catch{}(0,qe.spawnSync)("systemctl",["--user","daemon-reload"],{stdio:"ignore"})}(0,qe.spawnSync)("pkill",["-f","badgerclaw heartbeat"],{stdio:"ignore"})}function Rn(e){try{return $t.default.rmSync(e,{recursive:!0,force:!0}),!0}catch{return!1}}var En=new An.Command("logout").description("Disconnect this machine, log out of BadgerClaw, and wipe local state").option("--keep-state","Only clear auth.json (legacy behaviour); preserve bot-mapping, claude-sessions, heartbeat logs, and plugin quarantine ledger").action(async e=>{let t=S();if(t)try{let a=Ne(t.access_token),{version:l}=pe();await a.post("/api/v1/openclaw/register",{instance_id:t.instance_id,label:ke.default.hostname(),version:l,online:!1})}catch{}if(hs(),e.keepState){De(),console.log(Ke.default.green("Logged out \u2014 auth cleared. (state preserved with --keep-state)"));return}let o=Je.default.join(ke.default.homedir(),".badgerclaw"),n=Rn(o),r=Je.default.join(ke.default.homedir(),".openclaw","badgerclaw"),s=Rn(r);n||s?(console.log(Ke.default.green("Logged out \u2014 local state cleared.")),console.log(Ke.default.dim(` Removed: ${o}${s?`, ${r}`:""}`))):console.log(Ke.default.green("Logged out."))});var Pn=require("commander"),co=d(require("chalk"));N();var On=new Pn.Command("status").description("Show connected instance info").action(async()=>{let e=S();(!e||!nt())&&(console.log(co.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(co.default.green("Authenticated")),console.log(` User: ${rt(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var Re=require("commander"),b=d(require("chalk")),kt=d(require("ora")),It=d(require("fs")),Bn=d(require("os")),Mn=d(require("path")),Un=require("child_process");N();de();var xe=d(require("fs")),Dn=d(require("os")),Tn=d(require("path")),Ln=require("child_process");je();function vt(e){let t=e.split(":")[0].replace(/^@/,"").replace(/_bot$/,""),o=Tn.join(Dn.homedir(),".openclaw","openclaw.json");return xe.existsSync(o)?{changed:me(()=>{let r=JSON.parse(xe.readFileSync(o,"utf-8")),s=!1;if(r.channels?.badgerclaw?.accounts?.[t]&&(delete r.channels.badgerclaw.accounts[t],s=!0),r.agents?.list){let a=r.agents.list.length;r.agents.list=r.agents.list.filter(l=>l.id!==t),r.agents.list.length!==a&&(s=!0)}return s&&xe.writeFileSync(o,JSON.stringify(r,null,2)),s})}:{changed:!1}}function Ct(){try{return(0,Ln.execSync)("openclaw gateway restart",{stdio:"ignore"}),!0}catch{return!1}}fe();function Nn(e){return e.hermes?"hermes":"openclaw"}function jn(e){return e.openclaw.installed?"openclaw":e.hermes.installed?"hermes":"openclaw"}function uo(){nt()||(console.log(b.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function ys(e){return/^[a-z0-9_]{4,20}$/.test(e)}function Fn(e){return e.replace(/_bot$/,"")}var lo=["openclaw","hermes"],ws=new Re.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").option("-r, --runtime <runtime>",`Bot runtime: ${lo.join(" | ")}. Default is selected from this host's capabilities (Hermes preferred when available, OpenClaw otherwise \u2014 see \`badgerclaw setup\` output). Hermes requires HERMES_RUNTIME_ENABLED on the backend and a host that advertises Hermes capability via badgerclaw setup. Operator-side LLM credentials (BADGERCLAW_LLM_API_KEY or GOOGLE_API_KEY etc.) must be set at pair time, not at create time.`).action(async(e,t)=>{uo(),ys(e)||(console.log(b.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let o=t.runtime??jn(ge());lo.includes(o)||(console.log(b.default.red(`Invalid --runtime "${t.runtime}". Must be one of: ${lo.join(", ")}.`)),process.exit(1));let n=(0,kt.default)(`Creating ${o} bot "${e}"...`).start();try{let r=E();o==="hermes"?await r.post("/api/v1/bots",{bot_name:e,bot_username:e,runtime:"hermes"}):await r.post("/api/v1/openclaw/bots",{username:e}),n.succeed(b.default.green(`Bot "${e}" (${o}) created successfully!`)),o==="hermes"&&console.log(b.default.dim(" Next: generate a pair code from Adminweb (or POST /api/v1/pairing/create),\n then run `badgerclaw autopair` on a Hermes-capable host."))}catch(r){let s=r.response?.data?.errors?.[0]||r.message;n.fail(b.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),bs=new Re.Command("list").description("List your bots").action(async()=>{uo();let e=(0,kt.default)("Fetching bots...").start();try{let n=(await E().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),n.length===0){console.log(b.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(b.default.green(`Your bots (${n.length}):
125
- `));for(let r of n){let s=Fn(r.username||r.name),a=r.active===!1?b.default.dim("deactivated"):r.openclaw_connected?b.default.green("connected"):b.default.gray("disconnected");console.log(` ${b.default.bold(s)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(b.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),_s=new Re.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{uo();let t=(0,kt.default)(`Deactivating bot "${e}"...`).start();try{await E().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(b.default.green(`Bot "${e}" deactivated.`));let{changed:n}=vt(e);n&&(console.log(b.default.dim(" Removed from openclaw.json")),Ct()&&console.log(b.default.dim(" Gateway restarted")))}catch(o){let n=o.response?.data?.errors?.[0]||o.message;t.fail(b.default.red(`Failed to deactivate bot: ${n}`)),process.exit(1)}});function Ss(e){let t=e.trim();return t.startsWith("@")&&(t=t.slice(1)),t.includes(":")&&(t=t.split(":")[0]),Fn(t)}function $s(e){let t=e.replace(/[^a-zA-Z0-9_.-]/g,"_")||"default";return Mn.default.join(Bn.default.homedir(),".openclaw","badgerclaw","quarantine",`${t}.json`)}var vs=new Re.Command("refresh").description("Recover a bot stuck in quarantine \u2014 clears the quarantine ledger and restarts the gateway so the plugin's refresh chain runs from scratch").argument("<name>",'Bot name (e.g. "claude", "claude_bot", or full Matrix ID)').action(async e=>{let t=Ss(e);t||(console.log(b.default.red(`Couldn't parse bot name "${e}".`)),process.exit(1));let o=$s(t),n=!1;if(It.default.existsSync(o))try{let r=JSON.parse(It.default.readFileSync(o,"utf-8")),s=r.failureCount??"?",a=r.quarantinedAt??"?";console.log(b.default.dim(` Quarantine for "${t}" \u2014 ${s} failures, since ${a}`)),It.default.unlinkSync(o),n=!0}catch(r){console.log(b.default.red(`Failed to clear quarantine ledger at ${o}: ${r.message}`)),process.exit(1)}console.log(n?b.default.green(`\u2705 Cleared quarantine for "${t}"`):b.default.dim(` No quarantine file for "${t}" \u2014 already healthy or never quarantined.`)),console.log(b.default.dim(" Restarting OpenClaw gateway so the refresh chain runs..."));try{(0,Un.execSync)("openclaw gateway restart",{stdio:"inherit"})}catch(r){console.log(b.default.yellow(` Gateway restart command failed: ${r.message}`)),console.log(b.default.yellow(" Run `openclaw gateway restart` manually.")),process.exit(1)}console.log(b.default.green(`
126
- \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(b.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(b.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(b.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(b.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),Hn=new Re.Command("bot").description("Manage bots").addCommand(ws).addCommand(bs).addCommand(_s).addCommand(vs);He();var or=require("commander"),y=d(require("chalk"));N();ne();He();ye();Xe();ko();de();$e();var tr=3e3,sa=6e4,aa=2700*1e3,nr=new or.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{S()||(console.log(y.default.yellow("Not logged in.")),process.exit(1)),await Fe(!1),console.log(y.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=tr,n=null,r=null,s=()=>{let a=S();a||(console.log(y.default.red(" Auth missing \u2014 run `badgerclaw login` and re-start `badgerclaw watch`.")),process.exit(1));let l=new t(`${j}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${a.access_token}`}});r=l,l.onopen=()=>{o=tr,console.log(y.default.dim(" SSE connected \u2014 listening for events")),n&&clearTimeout(n),n=setTimeout(()=>{console.log(y.default.dim(" SSE proactive reconnect \u2014 refreshing token before expiry")),l.close(),s()},aa)},l.onerror=()=>{l.close(),n&&(clearTimeout(n),n=null),console.log(y.default.dim(` SSE disconnected \u2014 reconnecting in ${Math.floor(o/1e3)}s...`)),setTimeout(s,o),o=Math.min(o*1.5,sa)},l.onmessage=async c=>{try{let i=JSON.parse(c.data);if(i.type==="pair"){let u=i.target_instance_id;if(u&&u!==K()){console.log(y.default.dim(`
123
+ `}function ms(){try{return(0,z.execSync)("systemctl --user --version",{stdio:"ignore"}),!0}catch{return!1}}function _n(){if(wt.default.platform()==="linux"){if(!ms()){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=ls();yt.default.mkdirSync(bn,{recursive:!0}),yt.default.mkdirSync(We.default.join(wt.default.homedir(),".badgerclaw"),{recursive:!0}),yt.default.writeFileSync(cs,us(e)),(0,z.execSync)("systemctl --user daemon-reload",{stdio:"ignore"});try{(0,z.execSync)(`systemctl --user restart ${so}`,{stdio:"ignore"})}catch{}(0,z.execSync)(`systemctl --user enable --now ${so}`,{stdio:"ignore"});try{let t=(0,z.execSync)("whoami",{encoding:"utf-8"}).trim();(0,z.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 $n(){let e=Sn.default.platform();if(e==="darwin")return wn();if(e==="linux")return _n();console.log("\x1B[2mNote: background daemon install not supported on "+e+". Run `badgerclaw heartbeat` manually.\x1B[0m")}var ie=d(require("fs")),ao=d(require("os")),bt=d(require("path")),J=require("child_process"),H=d(require("chalk"));je();var vn=bt.default.join(ao.default.homedir(),".openclaw","openclaw.json");function ps(){return process.platform!=="linux"?!1:!!(ie.default.existsSync("/.dockerenv")||(0,J.spawnSync)("which",["systemctl"],{encoding:"utf-8"}).status!==0)}function Cn(e=!1){let t=null;try{ie.default.existsSync(vn)&&(t=JSON.parse(ie.default.readFileSync(vn,"utf-8"))?.gateway?.mode??null)}catch{}if(typeof t=="string"&&t.length>0)return!0;e||console.log(H.default.dim(" Setting gateway.mode=local..."));try{return me(()=>((0,J.execSync)("openclaw config set gateway.mode local",{encoding:"utf-8",timeout:1e4,stdio:"pipe"}),!0))}catch(o){return e||(console.log(H.default.yellow(` \u26A0\uFE0F Could not set gateway.mode automatically: ${o.message}`)),console.log(H.default.yellow(" Run `openclaw config set gateway.mode local` manually."))),!1}}function _t(e={}){let t=e.verbose!==!1,o=a=>{t&&console.log(a)};if(ps())return gs(t);o(H.default.dim(" Installing OpenClaw gateway service (if not present)...")),(0,J.spawnSync)("openclaw",["gateway","install"],{stdio:t?"inherit":"pipe",shell:!0}).status!==0&&o(H.default.yellow(" \u26A0\uFE0F `openclaw gateway install` returned non-zero \u2014 continuing.")),Cn(!t),o(H.default.dim(" Starting OpenClaw gateway..."));let r=(0,J.spawnSync)("openclaw",["gateway","start"],{stdio:t?"inherit":"pipe",shell:!0}),s="started";return r.status!==0&&(r=(0,J.spawnSync)("openclaw",["gateway","restart"],{stdio:t?"inherit":"pipe",shell:!0}),s="restarted"),r.status!==0?{ok:!1,error:"gateway start/restart returned non-zero exit"}:{ok:!0,state:s}}function gs(e){let t=i=>{e&&console.log(i)};t(H.default.dim(" Container mode (no systemd) \u2014 running gateway in foreground via nohup.")),Cn(!e);let o=bt.default.join(ao.default.homedir(),".openclaw","logs");try{ie.default.mkdirSync(o,{recursive:!0})}catch{}let n=bt.default.join(o,"gateway-foreground.log"),r,s;try{r=ie.default.openSync(n,"a"),s=ie.default.openSync(n,"a")}catch(i){return{ok:!1,error:`cannot open gateway log at ${n}: ${i.message}`}}let a=(0,J.spawn)("openclaw",["gateway"],{detached:!0,stdio:["ignore",r,s]});if(a.pid==null)return{ok:!1,error:"failed to spawn `openclaw gateway`"};a.unref(),t(H.default.dim(` Gateway PID: ${a.pid}, log: ${n}`));let l=Date.now()+2e4,c=!1;for(;Date.now()<l;){try{let u=ie.default.readFileSync(n,"utf-8");if(u.includes("[gateway] ready")){c=!0;break}if(/EADDRINUSE|FATAL|Error:|gateway start blocked/.test(u))return{ok:!1,error:`gateway aborted on startup \u2014 see ${n}`}}catch{}let i=new SharedArrayBuffer(4);Atomics.wait(new Int32Array(i),0,0,200)}return c?{ok:!0,state:"started"}:{ok:!1,error:`gateway did not report ready within 20s \u2014 see ${n}`}}function St(){if(process.platform!=="linux"||process.getuid?.()!==0)return;let e=(0,J.spawnSync)("loginctl",["show-user","root","--property=Linger"],{encoding:"utf-8"});e.status===0&&/Linger=no/.test(e.stdout||"")&&(console.log(H.default.yellow(`
124
+ \u26A0\uFE0F systemd lingering is OFF for root. The gateway will stop on SSH disconnect.`)),console.log(H.default.dim(" Enable persistence: loginctl enable-linger root")))}Ce();var fs=2e3,hs=12e4,Rn=new In.Command("login").description("Log in to BadgerClaw via browser").action(async()=>{let e=Oo(),t=Do(e),o=`${Bo}/cli-auth?code=${t}`;console.log(X.default.yellow("Opening browser for authentication...")),console.log(X.default.dim(`If the browser doesn't open, visit: ${o}`)),await(0,xn.default)(o);let n=(0,kn.default)("Waiting for authentication...").start(),r=Go(),s=Date.now();for(;Date.now()-s<hs;){try{let a=await r.post(`/api/v1/openclaw/cli/auth/poll/${t}`,{code_verifier:e,code_challenge:t});if(a.status===429){await new Promise(l=>setTimeout(l,5e3));continue}if(a.data?.access_token){let{access_token:l,user_id:c,expires_at:i,refresh_token:u,email:p}=a.data,A=Ut(),f=`openclaw-${io.default.hostname().toLowerCase().replace(/[^a-z0-9]/g,"-")}-${A}`,w=f;try{let{version:oe}=pe(),C=await r.post("/api/v1/openclaw/register",{instance_id:f,label:io.default.hostname(),version:oe,machine_fingerprint:A},{headers:{Authorization:`Bearer ${l}`}}),k=C.data?.result||C.data;k&&typeof k.instance_id=="string"&&k.instance_id.length>0&&(w=k.instance_id)}catch(oe){let C=oe?.response?.status;if(C===403||C===409){let k=oe?.response?.data,V=Array.isArray(k?.errors)&&typeof k.errors[0]=="string"?k.errors[0]:null,Pe=k?.detail,et=typeof Pe=="string"?Pe:Pe?.error==="downgrade_selection_required"?"Your account has an unresolved plan-change request. Open the BadgerClaw app to finish the downgrade selection, then try again.":null,Sr=V||et||`Login refused (status ${C}). Open the BadgerClaw app to check your subscription state.`;n.fail(X.default.red(Sr)),process.exit(1)}}ot({access_token:l,user_id:c,instance_id:w,expires_at:i,refresh_token:u,email:p}),n.succeed(X.default.green(`Logged in as ${rt(c)}`)),U()!==null?_t({verbose:!0}).ok||console.log(X.default.yellow("\n \u26A0\uFE0F Logged in, but gateway failed to start. Re-run `badgerclaw setup` to repair.")):console.log(X.default.dim(" Hermes-only host \u2014 skipping OpenClaw gateway bring-up."));let B=await Fe(!0);B>0&&console.log(X.default.green(`\u2705 ${B} bot(s) automatically paired to OpenClaw.`)),$n(),St();return}}catch{}await new Promise(a=>setTimeout(a,fs))}n.fail(X.default.red("Authentication timed out. Please try again.")),process.exit(1)});var En=require("commander"),Ke=d(require("chalk")),$t=d(require("fs")),ke=d(require("os")),Je=d(require("path")),qe=require("child_process");N();de();function ys(){let e=process.platform;if(e==="darwin"){let t=Je.default.join(ke.default.homedir(),"Library","LaunchAgents","ai.badgerclaw.watch.plist");(0,qe.spawnSync)("launchctl",["unload",t],{stdio:"ignore"});try{$t.default.unlinkSync(t)}catch{}}else if(e==="linux"){(0,qe.spawnSync)("systemctl",["--user","disable","--now","badgerclaw-watch.service"],{stdio:"ignore"});let t=Je.default.join(ke.default.homedir(),".config","systemd","user","badgerclaw-watch.service");try{$t.default.unlinkSync(t)}catch{}(0,qe.spawnSync)("systemctl",["--user","daemon-reload"],{stdio:"ignore"})}(0,qe.spawnSync)("pkill",["-f","badgerclaw heartbeat"],{stdio:"ignore"})}function An(e){try{return $t.default.rmSync(e,{recursive:!0,force:!0}),!0}catch{return!1}}var Pn=new En.Command("logout").description("Disconnect this machine, log out of BadgerClaw, and wipe local state").option("--keep-state","Only clear auth.json (legacy behaviour); preserve bot-mapping, claude-sessions, heartbeat logs, and plugin quarantine ledger").action(async e=>{let t=S();if(t)try{let a=Ne(t.access_token),{version:l}=pe();await a.post("/api/v1/openclaw/register",{instance_id:t.instance_id,label:ke.default.hostname(),version:l,online:!1})}catch{}if(ys(),e.keepState){De(),console.log(Ke.default.green("Logged out \u2014 auth cleared. (state preserved with --keep-state)"));return}let o=Je.default.join(ke.default.homedir(),".badgerclaw"),n=An(o),r=Je.default.join(ke.default.homedir(),".openclaw","badgerclaw"),s=An(r);n||s?(console.log(Ke.default.green("Logged out \u2014 local state cleared.")),console.log(Ke.default.dim(` Removed: ${o}${s?`, ${r}`:""}`))):console.log(Ke.default.green("Logged out."))});var On=require("commander"),co=d(require("chalk"));N();var Dn=new On.Command("status").description("Show connected instance info").action(async()=>{let e=S();(!e||!nt())&&(console.log(co.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1)),console.log(co.default.green("Authenticated")),console.log(` User: ${rt(e.user_id)}`),console.log(` Instance: ${e.instance_id}`),console.log(` Expires: ${new Date(e.expires_at).toLocaleDateString()}`)});var Re=require("commander"),b=d(require("chalk")),kt=d(require("ora")),It=d(require("fs")),Mn=d(require("os")),Un=d(require("path")),Fn=require("child_process");N();de();var xe=d(require("fs")),Tn=d(require("os")),Ln=d(require("path")),Nn=require("child_process");je();function vt(e){let t=e.split(":")[0].replace(/^@/,"").replace(/_bot$/,""),o=Ln.join(Tn.homedir(),".openclaw","openclaw.json");return xe.existsSync(o)?{changed:me(()=>{let r=JSON.parse(xe.readFileSync(o,"utf-8")),s=!1;if(r.channels?.badgerclaw?.accounts?.[t]&&(delete r.channels.badgerclaw.accounts[t],s=!0),r.agents?.list){let a=r.agents.list.length;r.agents.list=r.agents.list.filter(l=>l.id!==t),r.agents.list.length!==a&&(s=!0)}return s&&xe.writeFileSync(o,JSON.stringify(r,null,2)),s})}:{changed:!1}}function Ct(){try{return(0,Nn.execSync)("openclaw gateway restart",{stdio:"ignore"}),!0}catch{return!1}}fe();function jn(e){return e.hermes?"hermes":"openclaw"}function Bn(e){return e.openclaw.installed?"openclaw":e.hermes.installed?"hermes":"openclaw"}function uo(){nt()||(console.log(b.default.red("Not logged in. Run `badgerclaw login` to authenticate.")),process.exit(1))}function ws(e){return/^[a-z0-9_]{4,20}$/.test(e)}function Hn(e){return e.replace(/_bot$/,"")}var lo=["openclaw","hermes"],bs=new Re.Command("create").description("Create a new bot").argument("<name>","Bot name (4-20 chars, lowercase alphanumeric + underscores)").option("-r, --runtime <runtime>",`Bot runtime: ${lo.join(" | ")}. Default is selected from this host's capabilities (Hermes preferred when available, OpenClaw otherwise \u2014 see \`badgerclaw setup\` output). Hermes requires HERMES_RUNTIME_ENABLED on the backend and a host that advertises Hermes capability via badgerclaw setup. Operator-side LLM credentials (BADGERCLAW_LLM_API_KEY or GOOGLE_API_KEY etc.) must be set at pair time, not at create time.`).action(async(e,t)=>{uo(),ws(e)||(console.log(b.default.red("Invalid bot name. Must be 4-20 characters, lowercase alphanumeric and underscores only.")),process.exit(1));let o=t.runtime??Bn(ge());lo.includes(o)||(console.log(b.default.red(`Invalid --runtime "${t.runtime}". Must be one of: ${lo.join(", ")}.`)),process.exit(1));let n=(0,kt.default)(`Creating ${o} bot "${e}"...`).start();try{let r=E();o==="hermes"?await r.post("/api/v1/bots",{bot_name:e,bot_username:e,runtime:"hermes"}):await r.post("/api/v1/openclaw/bots",{username:e}),n.succeed(b.default.green(`Bot "${e}" (${o}) created successfully!`)),o==="hermes"&&console.log(b.default.dim(" Next: generate a pair code from Adminweb (or POST /api/v1/pairing/create),\n then run `badgerclaw autopair` on a Hermes-capable host."))}catch(r){let s=r.response?.data?.errors?.[0]||r.message;n.fail(b.default.red(`Failed to create bot: ${s}`)),process.exit(1)}}),_s=new Re.Command("list").description("List your bots").action(async()=>{uo();let e=(0,kt.default)("Fetching bots...").start();try{let n=(await E().get("/api/v1/openclaw/bots")).data?.bots||[];if(e.stop(),n.length===0){console.log(b.default.yellow("No bots found. Create one with `badgerclaw bot create <name>`."));return}console.log(b.default.green(`Your bots (${n.length}):
125
+ `));for(let r of n){let s=Hn(r.username||r.name),a=r.active===!1?b.default.dim("deactivated"):r.openclaw_connected?b.default.green("connected"):b.default.gray("disconnected");console.log(` ${b.default.bold(s)} ${a}`)}}catch(t){let o=t.response?.data?.errors?.[0]||t.message;e.fail(b.default.red(`Failed to list bots: ${o}`)),process.exit(1)}}),Ss=new Re.Command("delete").description("Deactivate a bot").argument("<name>","Bot name to deactivate").action(async e=>{uo();let t=(0,kt.default)(`Deactivating bot "${e}"...`).start();try{await E().delete(`/api/v1/openclaw/bots/${e}`),t.succeed(b.default.green(`Bot "${e}" deactivated.`));let{changed:n}=vt(e);n&&(console.log(b.default.dim(" Removed from openclaw.json")),Ct()&&console.log(b.default.dim(" Gateway restarted")))}catch(o){let n=o.response?.data?.errors?.[0]||o.message;t.fail(b.default.red(`Failed to deactivate bot: ${n}`)),process.exit(1)}});function $s(e){let t=e.trim();return t.startsWith("@")&&(t=t.slice(1)),t.includes(":")&&(t=t.split(":")[0]),Hn(t)}function vs(e){let t=e.replace(/[^a-zA-Z0-9_.-]/g,"_")||"default";return Un.default.join(Mn.default.homedir(),".openclaw","badgerclaw","quarantine",`${t}.json`)}var Cs=new Re.Command("refresh").description("Recover a bot stuck in quarantine \u2014 clears the quarantine ledger and restarts the gateway so the plugin's refresh chain runs from scratch").argument("<name>",'Bot name (e.g. "claude", "claude_bot", or full Matrix ID)').action(async e=>{let t=$s(e);t||(console.log(b.default.red(`Couldn't parse bot name "${e}".`)),process.exit(1));let o=vs(t),n=!1;if(It.default.existsSync(o))try{let r=JSON.parse(It.default.readFileSync(o,"utf-8")),s=r.failureCount??"?",a=r.quarantinedAt??"?";console.log(b.default.dim(` Quarantine for "${t}" \u2014 ${s} failures, since ${a}`)),It.default.unlinkSync(o),n=!0}catch(r){console.log(b.default.red(`Failed to clear quarantine ledger at ${o}: ${r.message}`)),process.exit(1)}console.log(n?b.default.green(`\u2705 Cleared quarantine for "${t}"`):b.default.dim(` No quarantine file for "${t}" \u2014 already healthy or never quarantined.`)),console.log(b.default.dim(" Restarting OpenClaw gateway so the refresh chain runs..."));try{(0,Fn.execSync)("openclaw gateway restart",{stdio:"inherit"})}catch(r){console.log(b.default.yellow(` Gateway restart command failed: ${r.message}`)),console.log(b.default.yellow(" Run `openclaw gateway restart` manually.")),process.exit(1)}console.log(b.default.green(`
126
+ \u2705 Refresh triggered. Watch the gateway logs for token refresh progress:`)),console.log(b.default.dim(" tail -f ~/.openclaw/logs/*.log")),console.log(b.default.dim(" If the bot fails to recover, the plugin's 4 refresh strategies all hit")),console.log(b.default.dim(" dead ends. Verify SYNAPSE_REGISTRATION_SHARED_SECRET is set on this gateway,")),console.log(b.default.dim(" or re-pair the bot from the BadgerClaw iOS app."))}),Gn=new Re.Command("bot").description("Manage bots").addCommand(bs).addCommand(_s).addCommand(Ss).addCommand(Cs);He();var nr=require("commander"),y=d(require("chalk"));N();ne();He();ye();Xe();ko();de();$e();var or=3e3,aa=6e4,ia=2700*1e3,rr=new nr.Command("watch").description("Watch for bot pair events in real-time (no polling)").action(async()=>{S()||(console.log(y.default.yellow("Not logged in.")),process.exit(1)),await Fe(!1),console.log(y.default.green("\u{1F534} Listening for pair events... (Ctrl+C to stop)"));let t=require("eventsource"),o=or,n=null,r=null,s=()=>{let a=S();a||(console.log(y.default.red(" Auth missing \u2014 run `badgerclaw login` and re-start `badgerclaw watch`.")),process.exit(1));let l=new t(`${j}/api/v1/openclaw/events`,{headers:{Authorization:`Bearer ${a.access_token}`}});r=l,l.onopen=()=>{o=or,console.log(y.default.dim(" SSE connected \u2014 listening for events")),n&&clearTimeout(n),n=setTimeout(()=>{console.log(y.default.dim(" SSE proactive reconnect \u2014 refreshing token before expiry")),l.close(),s()},ia)},l.onerror=()=>{l.close(),n&&(clearTimeout(n),n=null),console.log(y.default.dim(` SSE disconnected \u2014 reconnecting in ${Math.floor(o/1e3)}s...`)),setTimeout(s,o),o=Math.min(o*1.5,aa)},l.onmessage=async c=>{try{let i=JSON.parse(c.data);if(i.type==="pair"){let u=i.target_instance_id;if(u&&u!==K()){console.log(y.default.dim(`
127
127
  \u{1F4F1} Pair event for ${i.bot_name} targets ${u} \u2014 not us, skipping`));return}console.log(y.default.cyan(`
128
128
  \u{1F4F1} Pair event received: ${i.bot_name}`)),await Ue(i.pair_code,i.bot_name,i.bot_user_id,!1);try{let{execSync:p}=await import("child_process");p("openclaw gateway restart",{stdio:"ignore"}),console.log(y.default.green(" \u2705 Gateway restarted \u2014 bot is live!"))}catch{console.log(y.default.dim(" Gateway restart failed \u2014 run: openclaw gateway restart"))}}else if(i.type==="gateway-restart"){console.log(y.default.cyan(`
129
129
  \u{1F504} Remote gateway-restart command received`));let u=await Ae();u.success?console.log(y.default.green(` \u2705 Gateway restarted: ${u.message}`)):console.log(y.default.red(` \u274C Gateway restart failed: ${u.message}`));try{await O(),console.log(y.default.dim(" Heartbeat pushed with updated status."))}catch{console.log(y.default.dim(" Could not push heartbeat."))}}else if((i.type==="bot.delete"||i.type==="bot.disconnect")&&i.bot_user_id){let u=i.bot_user_id,p=i.type==="bot.delete"?"deleted":"disconnected",A=i.type==="bot.delete"?"\u{1F5D1}\uFE0F ":"\u{1F50C}";console.log(y.default.yellow(`
130
130
  ${A} Bot ${p}: ${u} \u2014 removing from OpenClaw config...`));try{let{changed:f}=vt(u);f?(console.log(y.default.green(" \u2705 Removed from openclaw.json")),Ct()?console.log(y.default.green(" \u2705 Gateway restarted")):console.log(y.default.dim(" Gateway restart failed \u2014 restart manually"))):console.log(y.default.dim(" Account not found in openclaw.json \u2014 nothing to remove"))}catch(f){console.log(y.default.red(` Failed to update openclaw.json: ${f}`))}}else if(i.type==="claude_code.start"&&i.bot_id&&i.room_id){console.log(y.default.cyan(`
131
131
  \u{1F916} Claude Code START received: bot=${i.bot_id} room=${i.room_id}`));try{let u=await Z({id:i.command_id||`cc-start-${Date.now()}`,command_type:"start_claude_code",payload:{bot_id:i.bot_id,room_id:i.room_id,session_id:i.session_id}});if(console.log(u.success?y.default.green(` \u2705 ${u.message}`):y.default.red(` \u274C ${u.message}`)),i.command_id)try{await E().post(`/api/v1/dashboard/commands/${i.command_id}/result`,{status:u.success?"success":"failed",result:u.message})}catch{}try{await O()}catch{}}catch(u){console.log(y.default.red(` Claude Code start error: ${u.message}`))}}else if(i.type==="claude_code.stop"&&i.bot_id&&i.room_id){console.log(y.default.cyan(`
132
132
  \u{1F916} Claude Code STOP received: bot=${i.bot_id} room=${i.room_id}`));try{let u=await Z({id:i.command_id||`cc-stop-${Date.now()}`,command_type:"stop_claude_code",payload:{bot_id:i.bot_id,room_id:i.room_id,session_id:i.session_id}});if(console.log(u.success?y.default.green(` \u2705 ${u.message}`):y.default.red(` \u274C ${u.message}`)),i.command_id)try{await E().post(`/api/v1/dashboard/commands/${i.command_id}/result`,{status:u.success?"success":"failed",result:u.message})}catch{}try{await O()}catch{}}catch(u){console.log(y.default.red(` Claude Code stop error: ${u.message}`))}}else if(i.type==="command.execute"&&i.command_id){console.log(y.default.cyan(`
133
- \u26A1 SSE command received: ${i.command_type} (${i.command_id})`));try{let u=E();await u.post(`/api/v1/dashboard/commands/${i.command_id}/ack`);let p=await Z({id:i.command_id,command_type:i.command_type,payload:i.payload});console.log(p.success?y.default.green(` \u2705 ${p.message}`):y.default.red(` \u274C ${p.message}`)),await u.post(`/api/v1/dashboard/commands/${i.command_id}/result`,{status:p.success?"success":"failed",result:p.message,new_version:p.newVersion||null});try{await O()}catch{}i.command_type==="update_cli"&&p.success&&(console.log(y.default.cyan(" CLI updated \u2014 restarting in 2s...")),setTimeout(()=>process.exit(0),2e3))}catch(u){console.log(y.default.red(` Command ${i.command_id} error: ${u.message}`))}}}catch{}}};s(),await new Promise(()=>{})});var dr=require("commander"),m=d(require("chalk")),ee=require("child_process"),I=d(require("fs")),Ze=d(require("os")),te=d(require("path"));ne();Ce();fe();var rr=require("child_process"),Tt=d(require("fs")),sr=d(require("os")),Lt=d(require("path"));fe();function ia(){let e=ar();for(let t of e)if(Tt.default.existsSync(t))return t;return null}function ar(){return[Lt.default.resolve(__dirname,"..","assets","hermes-agent-bc.Dockerfile"),Lt.default.resolve(__dirname,"..","..","assets","hermes-agent-bc.Dockerfile")]}function ir(){let e=ut();if(!e.installed)return{status:"no-docker"};let t=process.env.HERMES_IMAGE||Ie;if(mt(e).installed)return{status:"already-present",image:t};let n=ia();if(!n)return{status:"no-dockerfile",expectedPaths:ar()};let r=Tt.default.mkdtempSync(Lt.default.join(sr.default.tmpdir(),"bc-hermes-build-"));try{let s=(0,rr.spawnSync)("docker",["build","-t",t,"-f",n,r],{stdio:"inherit",timeout:6e5});return s.status===0?{status:"built",image:t}:{status:"build-failed",image:t,stderr:`docker build exited ${s.status??"<no-status>"}`}}finally{try{Tt.default.rmSync(r,{recursive:!0,force:!0})}catch{}}}var G=te.default.join(Ze.default.homedir(),".openclaw","openclaw.json"),Qe=G+".badgerclaw-stash",ur=te.default.join(Ze.default.homedir(),".openclaw","npm"),ca=te.default.join(ur,"package.json");async function la(){try{let e=await fetch(`${j}/api/v1/dashboard/versions/latest`,{headers:{Accept:"application/json"}});if(!e.ok)return{cli:null,plugin:null,openclaw:null};let t=await e.json(),o=t.result&&typeof t.result=="object"?t.result:t,n=r=>typeof r!="string"||!r||r==="unknown"?null:r;return{cli:n(o.cli),plugin:n(o.plugin),openclaw:n(o.supported_openclaw)}}catch{return{cli:null,plugin:null,openclaw:null}}}function da(){if(!I.default.existsSync(G))return null;try{let e=JSON.parse(I.default.readFileSync(G,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,I.default.writeFileSync(G,JSON.stringify(e,null,2)),I.default.writeFileSync(Qe,JSON.stringify(t,null,2)),t):null}catch{return null}}function ua(){if(!I.default.existsSync(G))return null;try{let e=JSON.parse(I.default.readFileSync(G,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function ma(e){if(e&&I.default.existsSync(G))try{let t=JSON.parse(I.default.readFileSync(G,"utf-8"));t.gateway={...e,...t.gateway||{}},I.default.writeFileSync(G,JSON.stringify(t,null,2))}catch(t){console.log(m.default.yellow(` \u26A0\uFE0F Could not restore gateway block: ${t.message}`)),console.log(m.default.yellow(" Run `openclaw config set gateway.mode local` manually if the gateway fails to start."))}}function pa(){if(I.default.existsSync(Qe))try{let e=JSON.parse(I.default.readFileSync(Qe,"utf-8")),t=JSON.parse(I.default.readFileSync(G,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,I.default.writeFileSync(G,JSON.stringify(t,null,2)),I.default.unlinkSync(Qe)}catch(e){console.log(m.default.yellow(` \u26A0\uFE0F Could not restore config: ${e.message}`)),console.log(m.default.yellow(` Your bot credentials are backed up at: ${Qe}`))}}async function cr(e){return new Promise(t=>{let o=(0,ee.spawn)("openclaw",["plugins","install",e,"--force","--dangerously-force-unsafe-install"],{stdio:["ignore","pipe","pipe"],shell:!0}),n="",r=!1,s=!1,a=/Installed plugin:|Restart the gateway to load plugins/,l=()=>{r||s||(r=!0,setTimeout(()=>{if(!s){try{o.kill("SIGTERM")}catch{}setTimeout(()=>{if(!s)try{o.kill("SIGKILL")}catch{}},1e3)}},3e3))},c=(i,u)=>{u.write(i),n+=i.toString("utf-8"),a.test(n)&&l()};o.stdout.on("data",i=>c(i,process.stdout)),o.stderr.on("data",i=>c(i,process.stderr)),o.on("exit",i=>{s=!0,t({status:r?0:i??1})}),o.on("error",i=>{s||(s=!0,console.error(m.default.red(` openclaw spawn error: ${i.message}`)),t({status:1}))})})}function lr(e){if(!I.default.existsSync(e))return!1;let t;try{t=JSON.parse(I.default.readFileSync(e,"utf-8"))}catch{return!1}let o=!1;return t.overrides&&typeof t.overrides=="object"&&"uuid"in t.overrides&&(delete t.overrides.uuid,o=!0),t.openclaw&&Array.isArray(t.openclaw.managedOverrides)&&t.openclaw.managedOverrides.includes("uuid")&&(t.openclaw.managedOverrides=t.openclaw.managedOverrides.filter(n=>n!=="uuid"),o=!0),o?(I.default.writeFileSync(e,JSON.stringify(t,null,2)+`
134
- `),!0):!1}function ga(){let e=[];lr(ca)&&e.push(ur);for(let t of lt())lr(te.default.join(t,"package.json"))&&e.push(t);return e}async function fa(){let{detectCapabilities:e}=await Promise.resolve().then(()=>(fe(),on)),{pushHeartbeat:t}=await Promise.resolve().then(()=>(Xe(),er));console.log(m.default.green(`
133
+ \u26A1 SSE command received: ${i.command_type} (${i.command_id})`));try{let u=E();await u.post(`/api/v1/dashboard/commands/${i.command_id}/ack`);let p=await Z({id:i.command_id,command_type:i.command_type,payload:i.payload});console.log(p.success?y.default.green(` \u2705 ${p.message}`):y.default.red(` \u274C ${p.message}`)),await u.post(`/api/v1/dashboard/commands/${i.command_id}/result`,{status:p.success?"success":"failed",result:p.message,new_version:p.newVersion||null});try{await O()}catch{}i.command_type==="update_cli"&&p.success&&(console.log(y.default.cyan(" CLI updated \u2014 restarting in 2s...")),setTimeout(()=>process.exit(0),2e3))}catch(u){console.log(y.default.red(` Command ${i.command_id} error: ${u.message}`))}}}catch{}}};s(),await new Promise(()=>{})});var ur=require("commander"),m=d(require("chalk")),ee=require("child_process"),I=d(require("fs")),Ze=d(require("os")),te=d(require("path"));ne();Ce();fe();var sr=require("child_process"),Tt=d(require("fs")),ar=d(require("os")),Lt=d(require("path"));fe();function ca(){let e=ir();for(let t of e)if(Tt.default.existsSync(t))return t;return null}function ir(){return[Lt.default.resolve(__dirname,"..","assets","hermes-agent-bc.Dockerfile"),Lt.default.resolve(__dirname,"..","..","assets","hermes-agent-bc.Dockerfile")]}function cr(){let e=ut();if(!e.installed)return{status:"no-docker"};let t=process.env.HERMES_IMAGE||Ie;if(mt(e).installed)return{status:"already-present",image:t};let n=ca();if(!n)return{status:"no-dockerfile",expectedPaths:ir()};let r=Tt.default.mkdtempSync(Lt.default.join(ar.default.tmpdir(),"bc-hermes-build-"));try{let s=(0,sr.spawnSync)("docker",["build","-t",t,"-f",n,r],{stdio:"inherit",timeout:6e5});return s.status===0?{status:"built",image:t}:{status:"build-failed",image:t,stderr:`docker build exited ${s.status??"<no-status>"}`}}finally{try{Tt.default.rmSync(r,{recursive:!0,force:!0})}catch{}}}var G=te.default.join(Ze.default.homedir(),".openclaw","openclaw.json"),Qe=G+".badgerclaw-stash",mr=te.default.join(Ze.default.homedir(),".openclaw","npm"),la=te.default.join(mr,"package.json");async function da(){try{let e=await fetch(`${j}/api/v1/dashboard/versions/latest`,{headers:{Accept:"application/json"}});if(!e.ok)return{cli:null,plugin:null,openclaw:null};let t=await e.json(),o=t.result&&typeof t.result=="object"?t.result:t,n=r=>typeof r!="string"||!r||r==="unknown"?null:r;return{cli:n(o.cli),plugin:n(o.plugin),openclaw:n(o.supported_openclaw)}}catch{return{cli:null,plugin:null,openclaw:null}}}function ua(){if(!I.default.existsSync(G))return null;try{let e=JSON.parse(I.default.readFileSync(G,"utf-8")),t=e.channels?.badgerclaw;return t?(delete e.channels.badgerclaw,e.plugins?.entries?.badgerclaw&&delete e.plugins.entries.badgerclaw,I.default.writeFileSync(G,JSON.stringify(e,null,2)),I.default.writeFileSync(Qe,JSON.stringify(t,null,2)),t):null}catch{return null}}function ma(){if(!I.default.existsSync(G))return null;try{let e=JSON.parse(I.default.readFileSync(G,"utf-8"));return!e.gateway||typeof e.gateway!="object"?null:JSON.parse(JSON.stringify(e.gateway))}catch{return null}}function pa(e){if(e&&I.default.existsSync(G))try{let t=JSON.parse(I.default.readFileSync(G,"utf-8"));t.gateway={...e,...t.gateway||{}},I.default.writeFileSync(G,JSON.stringify(t,null,2))}catch(t){console.log(m.default.yellow(` \u26A0\uFE0F Could not restore gateway block: ${t.message}`)),console.log(m.default.yellow(" Run `openclaw config set gateway.mode local` manually if the gateway fails to start."))}}function ga(){if(I.default.existsSync(Qe))try{let e=JSON.parse(I.default.readFileSync(Qe,"utf-8")),t=JSON.parse(I.default.readFileSync(G,"utf-8"));t.channels=t.channels||{},t.channels.badgerclaw=e,I.default.writeFileSync(G,JSON.stringify(t,null,2)),I.default.unlinkSync(Qe)}catch(e){console.log(m.default.yellow(` \u26A0\uFE0F Could not restore config: ${e.message}`)),console.log(m.default.yellow(` Your bot credentials are backed up at: ${Qe}`))}}async function lr(e){return new Promise(t=>{let o=(0,ee.spawn)("openclaw",["plugins","install",e,"--force","--dangerously-force-unsafe-install"],{stdio:["ignore","pipe","pipe"],shell:!0}),n="",r=!1,s=!1,a=/Installed plugin:|Restart the gateway to load plugins/,l=()=>{r||s||(r=!0,setTimeout(()=>{if(!s){try{o.kill("SIGTERM")}catch{}setTimeout(()=>{if(!s)try{o.kill("SIGKILL")}catch{}},1e3)}},3e3))},c=(i,u)=>{u.write(i),n+=i.toString("utf-8"),a.test(n)&&l()};o.stdout.on("data",i=>c(i,process.stdout)),o.stderr.on("data",i=>c(i,process.stderr)),o.on("exit",i=>{s=!0,t({status:r?0:i??1})}),o.on("error",i=>{s||(s=!0,console.error(m.default.red(` openclaw spawn error: ${i.message}`)),t({status:1}))})})}function dr(e){if(!I.default.existsSync(e))return!1;let t;try{t=JSON.parse(I.default.readFileSync(e,"utf-8"))}catch{return!1}let o=!1;return t.overrides&&typeof t.overrides=="object"&&"uuid"in t.overrides&&(delete t.overrides.uuid,o=!0),t.openclaw&&Array.isArray(t.openclaw.managedOverrides)&&t.openclaw.managedOverrides.includes("uuid")&&(t.openclaw.managedOverrides=t.openclaw.managedOverrides.filter(n=>n!=="uuid"),o=!0),o?(I.default.writeFileSync(e,JSON.stringify(t,null,2)+`
134
+ `),!0):!1}function fa(){let e=[];dr(la)&&e.push(mr);for(let t of lt())dr(te.default.join(t,"package.json"))&&e.push(t);return e}async function ha(){let{detectCapabilities:e}=await Promise.resolve().then(()=>(fe(),on)),{pushHeartbeat:t}=await Promise.resolve().then(()=>(Xe(),tr));console.log(m.default.green(`
135
135
  \u{1F9A1} BadgerClaw \u2014 capability refresh
136
136
  `));let o=e();console.log(m.default.dim(" Detected on this host:")),console.log(m.default.dim(` OpenClaw : ${Ro(o.openclaw)}`)),console.log(m.default.dim(` Hermes : ${Ro(o.hermes)}`)),console.log(m.default.dim(` Docker : ${Ro(o.docker)}`)),o.disk_free_gb!==null&&console.log(m.default.dim(` Disk free: ${o.disk_free_gb} GB`));try{await t(),console.log(m.default.green(`
137
137
  \u2705 Capabilities pushed to the API.`)),console.log(m.default.dim(" The backend will route new bot assignments accordingly."))}catch(n){let r=n?.message||String(n);if(r.includes("no auth")||r.includes("401")){console.log(m.default.yellow(`
138
138
  \u26A0\uFE0F Not logged in \u2014 capabilities re-scanned locally but not posted to the API.`)),console.log(m.default.dim(" Run `badgerclaw login` first, then re-run `badgerclaw setup --refresh`."));return}console.log(m.default.red(`
139
- \u274C Failed to push capabilities: ${r}`)),process.exit(1)}}function Ro(e){return e.installed?e.version?`installed (${e.version})`:e.image?`installed (${e.image})`:"installed":"not installed"}var mr=new dr.Command("setup").description("Install or update the OpenClaw BadgerClaw plugin safely (handles config automatically)").option("--refresh","Skip install steps; re-scan host capabilities and push them to the API immediately. Useful right after installing a second runtime (Docker, Hermes image) so the backend doesn't have to wait for the next heartbeat tick to pick up the change.").option("--hermes","Opt this host into the Hermes runtime instead of OpenClaw. Skips the OpenClaw binary + plugin + gateway install entirely; instead builds the Hermes container image locally from the bundled Dockerfile (against the public nousresearch/hermes-agent base on Docker Hub \u2014 no AWS/ECR credentials needed). Default (no flag) installs OpenClaw \u2014 Hermes is opt-in while it's still being soaked on early-adopter hosts.").action(async e=>{if(e.refresh){await fa();return}if(console.log(m.default.green(`
139
+ \u274C Failed to push capabilities: ${r}`)),process.exit(1)}}function Ro(e){return e.installed?e.version?`installed (${e.version})`:e.image?`installed (${e.image})`:"installed":"not installed"}var pr=new ur.Command("setup").description("Install or update the OpenClaw BadgerClaw plugin safely (handles config automatically)").option("--refresh","Skip install steps; re-scan host capabilities and push them to the API immediately. Useful right after installing a second runtime (Docker, Hermes image) so the backend doesn't have to wait for the next heartbeat tick to pick up the change.").option("--hermes","Opt this host into the Hermes runtime instead of OpenClaw. Skips the OpenClaw binary + plugin + gateway install entirely; instead builds the Hermes container image locally from the bundled Dockerfile (against the public nousresearch/hermes-agent base on Docker Hub \u2014 no AWS/ECR credentials needed). Default (no flag) installs OpenClaw \u2014 Hermes is opt-in while it's still being soaked on early-adopter hosts.").action(async e=>{if(e.refresh){await ha();return}if(console.log(m.default.green(`
140
140
  \u{1F9A1} BadgerClaw Setup
141
- `)),Nn({hermes:e.hermes})==="hermes"){let f=ge();if(console.log(m.default.dim(` Detected: Docker ${f.docker.installed?"running":"not running"}, Hermes image ${f.hermes.installed?"present":"absent"}.`)),console.log(m.default.dim(` Selected runtime: ${m.default.cyan("hermes")} (via --hermes flag)
142
- `)),f.docker.installed||(console.log(m.default.red("\u274C Docker is not running \u2014 required for the Hermes runtime.")),console.log(m.default.dim(" Install Docker Desktop (or colima on macOS / docker-ce on Linux) and start it,")),console.log(m.default.dim(" then re-run `badgerclaw setup --hermes`.")),process.exit(1)),f.hermes.installed)console.log(m.default.dim(` Hermes image already present: ${f.hermes.image}`));else{console.log(m.default.dim(" Building Hermes image (one-time, ~2 min)..."));let w=ir();w.status==="built"?console.log(m.default.green(` \u2705 Hermes image built: ${w.image}`)):w.status==="already-present"?console.log(m.default.dim(` Hermes image already present: ${w.image}`)):w.status==="no-dockerfile"?(console.log(m.default.red(`
141
+ `)),jn({hermes:e.hermes})==="hermes"){let f=ge();if(console.log(m.default.dim(` Detected: Docker ${f.docker.installed?"running":"not running"}, Hermes image ${f.hermes.installed?"present":"absent"}.`)),console.log(m.default.dim(` Selected runtime: ${m.default.cyan("hermes")} (via --hermes flag)
142
+ `)),f.docker.installed||(console.log(m.default.red("\u274C Docker is not running \u2014 required for the Hermes runtime.")),console.log(m.default.dim(" Install Docker Desktop (or colima on macOS / docker-ce on Linux) and start it,")),console.log(m.default.dim(" then re-run `badgerclaw setup --hermes`.")),process.exit(1)),f.hermes.installed)console.log(m.default.dim(` Hermes image already present: ${f.hermes.image}`));else{console.log(m.default.dim(" Building Hermes image (one-time, ~2 min)..."));let w=cr();w.status==="built"?console.log(m.default.green(` \u2705 Hermes image built: ${w.image}`)):w.status==="already-present"?console.log(m.default.dim(` Hermes image already present: ${w.image}`)):w.status==="no-dockerfile"?(console.log(m.default.red(`
143
143
  \u274C Bundled Hermes Dockerfile missing from CLI install.`)),console.log(m.default.dim(" Reinstall: npm install -g badgerclaw@latest")),console.log(m.default.dim(` Looked at: ${w.expectedPaths.join(", ")}`)),process.exit(1)):w.status==="build-failed"?(console.log(m.default.red(`
144
144
  \u274C Hermes image build failed: ${w.stderr}`)),console.log(m.default.dim(" See the docker output above for details.")),process.exit(1)):w.status==="no-docker"&&(console.log(m.default.red(`
145
145
  \u274C Docker is not running.`)),process.exit(1))}console.log(m.default.dim(`
146
146
  Hermes-only mode \u2014 skipping OpenClaw plugin + gateway install.
147
147
  To enable OC bots later, drop the --hermes flag: \`badgerclaw setup\`.
148
- `)),console.log(m.default.green("\u2705 Setup complete (Hermes-only host).")),console.log(m.default.dim("\nNext steps:\n 1. `badgerclaw login` \u2014 authenticate this CLI to the backend.\n 2. `badgerclaw setup --refresh` \u2014 push the Hermes capability so\n the backend (and the iOS app) knows this host can serve\n Hermes bots.\n 3. `badgerclaw bot create <name>` \u2014 defaults to Hermes on this host."));return}let o=await la();if(o.cli){let f=qt();f!==o.cli?(console.log(m.default.dim(` Updating CLI: ${f} \u2192 ${o.cli} (supported)...`)),(0,ee.spawnSync)("npm",["install","-g",`badgerclaw@${o.cli}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(m.default.red("\n\u274C CLI update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(m.default.green(` \u2705 CLI updated to ${o.cli}`))):console.log(m.default.dim(` CLI already at approved version ${f}.`))}if(o.openclaw){let f=U();f!==o.openclaw?(console.log(f===null?m.default.dim(` Installing OpenClaw ${o.openclaw} (supported)...`):m.default.dim(` Updating OpenClaw: ${f} \u2192 ${o.openclaw} (supported)...`)),(0,ee.spawnSync)("npm",["install","-g",`openclaw@${o.openclaw}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(m.default.red("\n\u274C OpenClaw install/update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(m.default.green(` \u2705 OpenClaw at ${o.openclaw}`))):console.log(m.default.dim(` OpenClaw already at approved version ${f}.`))}else U()===null&&(console.log(m.default.yellow(" \u26A0\uFE0F No approved OpenClaw version and none installed \u2014 installing latest from npm.")),(0,ee.spawnSync)("npm",["install","-g","openclaw"],{stdio:"inherit",shell:!0}).status!==0&&(console.log(m.default.red(`
149
- \u274C OpenClaw install failed.`)),process.exit(1)));let n=da();n&&console.log(m.default.dim(" Existing bot config stashed temporarily..."));let r=ua();(0,ee.spawnSync)("openclaw",["gateway","stop"],{stdio:"pipe",shell:!0,timeout:1e4});let s=[te.default.join(Ze.default.homedir(),".openclaw","extensions","badgerclaw"),te.default.join(Ze.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),...lt()],a=[],l=[],c=f=>{let w=`${f}.bc-setup-stash-${Date.now()}-${Math.floor(Math.random()*1e6)}`,B=(0,ee.spawnSync)("mv",["-f",f,w],{encoding:"utf-8"});return B.status===0?{ok:!0,stash:w}:{ok:!1,error:(B.stderr||"").trim()||`exit ${B.status}`}};for(let f of s)if(I.default.existsSync(f))try{I.default.rmSync(f,{recursive:!0,force:!0}),a.push(f)}catch(w){let B=c(f);B.ok?(l.push(`${f} \u2192 ${B.stash}`),console.log(m.default.yellow(` \u26A0\uFE0F Could not delete ${f} (${w.message}); renamed it aside instead.`))):(console.log(m.default.red(` \u274C Could not delete ${f} (${w.message})`)),console.log(m.default.red(` Could not rename ${f} aside either (${B.error}). Plugin install will likely fail.`)))}a.length>0&&console.log(m.default.dim(` Cleared existing plugin director${a.length>1?"ies":"y"}.`)),l.length>0&&console.log(m.default.dim(` Renamed busy install${l.length>1?"s":""} aside: ${l.join(", ")}`));let i=o.plugin?`@badgerclaw/connect@${o.plugin}`:"@badgerclaw/connect";o.plugin?console.log(m.default.dim(` Installing ${i} (supported)...`)):console.log(m.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let u=await cr(i);if(u.status===0&&o.plugin&&o.plugin!=="unknown"){for(let w=1;w<=2&&!(dt()===o.plugin||(console.log(m.default.yellow(` Plugin landed as a hook-pack-only install (not yet visible to \`badgerclaw login\`) \u2014 re-running plugin install (attempt ${w}/2)...`)),u=await cr(i),u.status!==0));w++);u.status===0&&dt()!==o.plugin&&console.log(m.default.yellow(" \u26A0\uFE0F Plugin still not detected at the npm install path after 2 attempt(s). If `badgerclaw login` reports it as not installed, re-run `badgerclaw setup`."))}n&&(pa(),console.log(m.default.dim(" Bot config restored."))),r&&(ma(r),console.log(m.default.dim(" Gateway config restored."))),u.status!==0&&(console.log(m.default.red(`
148
+ `)),console.log(m.default.green("\u2705 Setup complete (Hermes-only host).")),console.log(m.default.dim("\nNext steps:\n 1. `badgerclaw login` \u2014 authenticate this CLI to the backend.\n 2. `badgerclaw setup --refresh` \u2014 push the Hermes capability so\n the backend (and the iOS app) knows this host can serve\n Hermes bots.\n 3. `badgerclaw bot create <name>` \u2014 defaults to Hermes on this host."));return}let o=await da();if(o.cli){let f=qt();f!==o.cli?(console.log(m.default.dim(` Updating CLI: ${f} \u2192 ${o.cli} (supported)...`)),(0,ee.spawnSync)("npm",["install","-g",`badgerclaw@${o.cli}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(m.default.red("\n\u274C CLI update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(m.default.green(` \u2705 CLI updated to ${o.cli}`))):console.log(m.default.dim(` CLI already at approved version ${f}.`))}if(o.openclaw){let f=U();f!==o.openclaw?(console.log(f===null?m.default.dim(` Installing OpenClaw ${o.openclaw} (supported)...`):m.default.dim(` Updating OpenClaw: ${f} \u2192 ${o.openclaw} (supported)...`)),(0,ee.spawnSync)("npm",["install","-g",`openclaw@${o.openclaw}`],{stdio:"inherit",shell:!0}).status!==0&&(console.log(m.default.red("\n\u274C OpenClaw install/update failed. Fix the npm error above, then re-run `badgerclaw setup`.")),process.exit(1)),console.log(m.default.green(` \u2705 OpenClaw at ${o.openclaw}`))):console.log(m.default.dim(` OpenClaw already at approved version ${f}.`))}else U()===null&&(console.log(m.default.yellow(" \u26A0\uFE0F No approved OpenClaw version and none installed \u2014 installing latest from npm.")),(0,ee.spawnSync)("npm",["install","-g","openclaw"],{stdio:"inherit",shell:!0}).status!==0&&(console.log(m.default.red(`
149
+ \u274C OpenClaw install failed.`)),process.exit(1)));let n=ua();n&&console.log(m.default.dim(" Existing bot config stashed temporarily..."));let r=ma();(0,ee.spawnSync)("openclaw",["gateway","stop"],{stdio:"pipe",shell:!0,timeout:1e4});let s=[te.default.join(Ze.default.homedir(),".openclaw","extensions","badgerclaw"),te.default.join(Ze.default.homedir(),".openclaw","npm","node_modules","@badgerclaw","connect"),...lt()],a=[],l=[],c=f=>{let w=`${f}.bc-setup-stash-${Date.now()}-${Math.floor(Math.random()*1e6)}`,B=(0,ee.spawnSync)("mv",["-f",f,w],{encoding:"utf-8"});return B.status===0?{ok:!0,stash:w}:{ok:!1,error:(B.stderr||"").trim()||`exit ${B.status}`}};for(let f of s)if(I.default.existsSync(f))try{I.default.rmSync(f,{recursive:!0,force:!0}),a.push(f)}catch(w){let B=c(f);B.ok?(l.push(`${f} \u2192 ${B.stash}`),console.log(m.default.yellow(` \u26A0\uFE0F Could not delete ${f} (${w.message}); renamed it aside instead.`))):(console.log(m.default.red(` \u274C Could not delete ${f} (${w.message})`)),console.log(m.default.red(` Could not rename ${f} aside either (${B.error}). Plugin install will likely fail.`)))}a.length>0&&console.log(m.default.dim(` Cleared existing plugin director${a.length>1?"ies":"y"}.`)),l.length>0&&console.log(m.default.dim(` Renamed busy install${l.length>1?"s":""} aside: ${l.join(", ")}`));let i=o.plugin?`@badgerclaw/connect@${o.plugin}`:"@badgerclaw/connect";o.plugin?console.log(m.default.dim(` Installing ${i} (supported)...`)):console.log(m.default.yellow(" \u26A0\uFE0F Allow-list unavailable \u2014 installing @badgerclaw/connect unpinned."));let u=await lr(i);if(u.status===0&&o.plugin&&o.plugin!=="unknown"){for(let w=1;w<=2&&!(dt()===o.plugin||(console.log(m.default.yellow(` Plugin landed as a hook-pack-only install (not yet visible to \`badgerclaw login\`) \u2014 re-running plugin install (attempt ${w}/2)...`)),u=await lr(i),u.status!==0));w++);u.status===0&&dt()!==o.plugin&&console.log(m.default.yellow(" \u26A0\uFE0F Plugin still not detected at the npm install path after 2 attempt(s). If `badgerclaw login` reports it as not installed, re-run `badgerclaw setup`."))}n&&(ga(),console.log(m.default.dim(" Bot config restored."))),r&&(pa(r),console.log(m.default.dim(" Gateway config restored."))),u.status!==0&&(console.log(m.default.red(`
150
150
  \u274C Plugin install failed. Your bot config has been restored.`)),process.exit(1)),console.log(m.default.green(`
151
- \u2705 BadgerClaw plugin installed successfully!`));let p=ga();for(let f of p){console.log(m.default.dim(` Stripping OpenClaw uuid:14 override in ${f} (breaks request@2.88 in matrix-bot-sdk)...`));try{I.default.rmSync(te.default.join(f,"node_modules","uuid"),{recursive:!0,force:!0})}catch{}try{I.default.rmSync(te.default.join(f,"package-lock.json"),{force:!0})}catch{}(0,ee.spawnSync)("npm",["install"],{cwd:f,stdio:"inherit",shell:!0}).status!==0&&(console.log(m.default.red(`
151
+ \u2705 BadgerClaw plugin installed successfully!`));let p=fa();for(let f of p){console.log(m.default.dim(` Stripping OpenClaw uuid:14 override in ${f} (breaks request@2.88 in matrix-bot-sdk)...`));try{I.default.rmSync(te.default.join(f,"node_modules","uuid"),{recursive:!0,force:!0})}catch{}try{I.default.rmSync(te.default.join(f,"package-lock.json"),{force:!0})}catch{}(0,ee.spawnSync)("npm",["install"],{cwd:f,stdio:"inherit",shell:!0}).status!==0&&(console.log(m.default.red(`
152
152
  \u274C npm install failed after removing uuid override. Bot will not reply correctly until this is resolved.`)),process.exit(1))}p.length>0&&console.log(m.default.green(" \u2705 uuid override stripped + npm tree re-resolved.")),console.log(""),_t({verbose:!0}).ok||(console.log(m.default.red(`
153
- \u274C Gateway failed to start. Diagnose with:`)),console.log(m.default.dim(" systemctl --user status openclaw-gateway.service # Linux")),console.log(m.default.dim(" launchctl list | grep openclaw # macOS")),console.log(m.default.dim(" openclaw config get gateway.mode")),console.log(m.default.dim(" Then re-run `badgerclaw setup` after fixing the underlying issue.")),process.exit(1)),console.log(m.default.green(" \u2705 Gateway is running.")),console.log(m.default.dim("\nNext: run `badgerclaw login` to authenticate.")),St()});Xe();var gr=require("commander"),x=d(require("chalk"));N();$e();ye();var fr=new gr.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{S()||(console.log(x.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=pe(),o=st(),n=await Ye();console.log(x.default.bold.green(`
153
+ \u274C Gateway failed to start. Diagnose with:`)),console.log(m.default.dim(" systemctl --user status openclaw-gateway.service # Linux")),console.log(m.default.dim(" launchctl list | grep openclaw # macOS")),console.log(m.default.dim(" openclaw config get gateway.mode")),console.log(m.default.dim(" Then re-run `badgerclaw setup` after fixing the underlying issue.")),process.exit(1)),console.log(m.default.green(" \u2705 Gateway is running.")),console.log(m.default.dim("\nNext: run `badgerclaw login` to authenticate.")),St()});Xe();var fr=require("commander"),x=d(require("chalk"));N();$e();ye();var hr=new fr.Command("dashboard").description("Show local diagnostic dashboard \u2014 machine health, gateway status, bot telemetry").action(async()=>{S()||(console.log(x.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let{version:t}=pe(),o=st(),n=await Ye();console.log(x.default.bold.green(`
154
154
  BadgerClaw Dashboard
155
- `)),console.log(x.default.bold(" Instance")),console.log(` ID: ${K()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${n.pluginVersion}`),console.log(),console.log(x.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${pr(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let r=n.status==="running"?x.default.green:n.status==="error"?x.default.red:x.default.yellow;if(console.log(x.default.bold(" Gateway")),console.log(` Status: ${r(n.status)}`),console.log(` PID: ${n.pid??"N/A"}`),console.log(` Last Restart: ${n.lastRestart??"N/A"}`),console.log(),n.bots.length===0)console.log(x.default.bold(" Bots")),console.log(x.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log(x.default.bold(` Bots (${n.bots.length})`)),console.log();for(let s of n.bots){let a=s.status==="running"?x.default.green:s.status==="error"?x.default.red:x.default.yellow;if(console.log(` ${x.default.bold(s.botUsername)} ${a(`[${s.status}]`)}`),console.log(` ID: ${s.botId}`),console.log(` Uptime: ${pr(s.uptimeSeconds)}`),console.log(` Messages: ${s.messagesReceived} in / ${s.messagesSent} out`),s.chunkedMessages>0&&console.log(` Chunked: ${s.chunkedMessages} messages, ${s.totalChunksSent} chunks`),console.log(` Rooms: ${s.roomsActive} active`),console.log(` Errors: ${s.errors}`),s.lastError&&(console.log(` Last Error: ${x.default.red(s.lastError)}`),console.log(` Error At: ${s.lastErrorAt}`)),console.log(` Last Active: ${s.lastActivity??"N/A"}`),s.roomDetails&&s.roomDetails.length>0){console.log(x.default.dim(" Rooms:"));for(let l of s.roomDetails)console.log(x.default.dim(` ${l.roomName} \u2014 ${l.messagesInRoom} msgs, last: ${l.lastActivityInRoom??"N/A"}`))}console.log()}}console.log(x.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function pr(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 Ao=require("commander"),Ee=d(require("chalk")),hr=d(require("ora"));N();ye();Xe();var ha=new Ao.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{S()||(console.log(Ee.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,hr.default)("Restarting gateway...").start(),o=await Ae();if(o.success){t.succeed(Ee.default.green(`Gateway restarted: ${o.message}`));try{await O(),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)}),yr=new Ao.Command("gateway").description("Manage the OpenClaw gateway").addCommand(ha);var le=require("commander"),_=d(require("chalk")),Se=d(require("ora")),ce=d(require("axios"));Et();N();var _e="http://localhost:7331",ya=new le.Command("start").description("Start a Claude Code session for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID (default: auto-generated)").option("--port <port>","MCP server port (default: 7332)","7332").option("--project <dir>","Project directory",process.cwd()).action(async e=>{S()||(console.log(_.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=e.sessionId||`session-${Date.now()}`,n=parseInt(e.port,10),r=e.project.replace(/^~/,process.env.HOME||""),s=(0,Se.default)("Starting Claude Code session...").start();try{await ce.default.post(`${_e}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),s.text="Gateway toggled \u2014 launching MCP server...";let l=bo({sessionId:o,port:n,projectDir:r}).pid||0;await new Promise(c=>setTimeout(c,1500)),s.text="MCP server running \u2014 launching Claude Code...",_o({sessionId:o,port:n,projectDir:r}),So(o,0,l,n,r),s.succeed(_.default.green("Claude Code session started")+_.default.dim(` (session: ${o}, port: ${n})`)),console.log(_.default.dim(` Bot: ${e.bot}`)),console.log(_.default.dim(` Room: ${e.room}`)),console.log(_.default.dim(` Project: ${r}`)),console.log(_.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let l=a.response?.data?.message||a.message||"Unknown error";s.fail(_.default.red(`Failed to start Claude Code: ${l}`)),process.exit(1)}}),wa=new le.Command("stop").description("Stop a Claude Code session").option("--bot <botId>","Bot ID or username").option("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID to stop").action(async e=>{S()||(console.log(_.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,Se.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await ce.default.post(`${_e}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let n=e.sessionId;if(!n)try{let a=((await ce.default.get(`${_e}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(l=>l.botId===e.bot&&l.roomId===e.room);a&&(n=a.sessionId)}catch{}n?($o(n),o.succeed(_.default.green(`Claude Code session stopped (${n})`))):(o.succeed(_.default.green("Claude Code toggled off at gateway")),console.log(_.default.dim(" No local session found to kill \u2014 may need to close Claude Code manually.")))}catch(n){let r=n.response?.data?.message||n.message||"Unknown error";o.fail(_.default.red(`Failed to stop Claude Code: ${r}`)),process.exit(1)}}),ba=new le.Command("status").description("Show active Claude Code sessions").action(async()=>{S()||(console.log(_.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,Se.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await ce.default.get(`${_e}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let n=vo();if(t.stop(),o.length===0&&n.length===0){console.log(_.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(_.default.bold(`
155
+ `)),console.log(x.default.bold(" Instance")),console.log(` ID: ${K()}`),console.log(` CLI Version: ${t}`),console.log(` Plugin: ${n.pluginVersion}`),console.log(),console.log(x.default.bold(" Machine")),console.log(` Hostname: ${o.hostname}`),console.log(` OS: ${o.os} / ${o.arch}`),console.log(` Uptime: ${gr(o.uptimeSeconds)}`),console.log(` Free Memory: ${o.memFreeMb} MB`),console.log();let r=n.status==="running"?x.default.green:n.status==="error"?x.default.red:x.default.yellow;if(console.log(x.default.bold(" Gateway")),console.log(` Status: ${r(n.status)}`),console.log(` PID: ${n.pid??"N/A"}`),console.log(` Last Restart: ${n.lastRestart??"N/A"}`),console.log(),n.bots.length===0)console.log(x.default.bold(" Bots")),console.log(x.default.dim(" No bots detected. Pair bots at https://badgerclaw.ai")),console.log();else{console.log(x.default.bold(` Bots (${n.bots.length})`)),console.log();for(let s of n.bots){let a=s.status==="running"?x.default.green:s.status==="error"?x.default.red:x.default.yellow;if(console.log(` ${x.default.bold(s.botUsername)} ${a(`[${s.status}]`)}`),console.log(` ID: ${s.botId}`),console.log(` Uptime: ${gr(s.uptimeSeconds)}`),console.log(` Messages: ${s.messagesReceived} in / ${s.messagesSent} out`),s.chunkedMessages>0&&console.log(` Chunked: ${s.chunkedMessages} messages, ${s.totalChunksSent} chunks`),console.log(` Rooms: ${s.roomsActive} active`),console.log(` Errors: ${s.errors}`),s.lastError&&(console.log(` Last Error: ${x.default.red(s.lastError)}`),console.log(` Error At: ${s.lastErrorAt}`)),console.log(` Last Active: ${s.lastActivity??"N/A"}`),s.roomDetails&&s.roomDetails.length>0){console.log(x.default.dim(" Rooms:"));for(let l of s.roomDetails)console.log(x.default.dim(` ${l.roomName} \u2014 ${l.messagesInRoom} msgs, last: ${l.lastActivityInRoom??"N/A"}`))}console.log()}}console.log(x.default.dim(` Last checked: ${new Date().toISOString()}`)),console.log()});function gr(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 Ao=require("commander"),Ee=d(require("chalk")),yr=d(require("ora"));N();ye();Xe();var ya=new Ao.Command("restart").description("Restart the OpenClaw gateway via the plugin probe endpoint").action(async()=>{S()||(console.log(Ee.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,yr.default)("Restarting gateway...").start(),o=await Ae();if(o.success){t.succeed(Ee.default.green(`Gateway restarted: ${o.message}`));try{await O(),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)}),wr=new Ao.Command("gateway").description("Manage the OpenClaw gateway").addCommand(ya);var le=require("commander"),_=d(require("chalk")),Se=d(require("ora")),ce=d(require("axios"));Et();N();var _e="http://localhost:7331",wa=new le.Command("start").description("Start a Claude Code session for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID (default: auto-generated)").option("--port <port>","MCP server port (default: 7332)","7332").option("--project <dir>","Project directory",process.cwd()).action(async e=>{S()||(console.log(_.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=e.sessionId||`session-${Date.now()}`,n=parseInt(e.port,10),r=e.project.replace(/^~/,process.env.HOME||""),s=(0,Se.default)("Starting Claude Code session...").start();try{await ce.default.post(`${_e}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:o},{timeout:1e4}),s.text="Gateway toggled \u2014 launching MCP server...";let l=bo({sessionId:o,port:n,projectDir:r}).pid||0;await new Promise(c=>setTimeout(c,1500)),s.text="MCP server running \u2014 launching Claude Code...",_o({sessionId:o,port:n,projectDir:r}),So(o,0,l,n,r),s.succeed(_.default.green("Claude Code session started")+_.default.dim(` (session: ${o}, port: ${n})`)),console.log(_.default.dim(` Bot: ${e.bot}`)),console.log(_.default.dim(` Room: ${e.room}`)),console.log(_.default.dim(` Project: ${r}`)),console.log(_.default.dim(" Claude Code should open in a new terminal window."))}catch(a){let l=a.response?.data?.message||a.message||"Unknown error";s.fail(_.default.red(`Failed to start Claude Code: ${l}`)),process.exit(1)}}),ba=new le.Command("stop").description("Stop a Claude Code session").option("--bot <botId>","Bot ID or username").option("--room <roomId>","Matrix room ID").option("--session-id <id>","Session ID to stop").action(async e=>{S()||(console.log(_.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let o=(0,Se.default)("Stopping Claude Code session...").start();try{e.bot&&e.room&&await ce.default.post(`${_e}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!1},{timeout:1e4});let n=e.sessionId;if(!n)try{let a=((await ce.default.get(`${_e}/claude-code/status`,{timeout:5e3})).data?.rooms||[]).find(l=>l.botId===e.bot&&l.roomId===e.room);a&&(n=a.sessionId)}catch{}n?($o(n),o.succeed(_.default.green(`Claude Code session stopped (${n})`))):(o.succeed(_.default.green("Claude Code toggled off at gateway")),console.log(_.default.dim(" No local session found to kill \u2014 may need to close Claude Code manually.")))}catch(n){let r=n.response?.data?.message||n.message||"Unknown error";o.fail(_.default.red(`Failed to stop Claude Code: ${r}`)),process.exit(1)}}),_a=new le.Command("status").description("Show active Claude Code sessions").action(async()=>{S()||(console.log(_.default.yellow("Not logged in. Run `badgerclaw login` first.")),process.exit(1));let t=(0,Se.default)("Fetching Claude Code status...").start();try{let o=[];try{o=(await ce.default.get(`${_e}/claude-code/status`,{timeout:5e3})).data?.rooms||[]}catch{}let n=vo();if(t.stop(),o.length===0&&n.length===0){console.log(_.default.dim("No active Claude Code sessions."));return}if(o.length>0){console.log(_.default.bold(`
156
156
  Gateway Claude Code Rooms:`)),console.log(_.default.dim(" Bot".padEnd(30)+"Room".padEnd(30)+"Session".padEnd(20)+"Enabled")),console.log(_.default.dim(" "+"-".repeat(88)));for(let r of o){let s=r.enabled?_.default.green("ON"):_.default.dim("OFF");console.log(` ${(r.botId||"").padEnd(30)}${(r.roomName||r.roomId||"").padEnd(30)}${(r.sessionId||"-").padEnd(20)}${s}`)}}if(n.length>0){console.log(_.default.bold(`
157
- Local Sessions:`)),console.log(_.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(_.default.dim(" "+"-".repeat(90)));for(let r of n)console.log(` ${r.sessionId.padEnd(25)}${String(r.port).padEnd(8)}${String(r.mcpPid).padEnd(10)}${r.projectDir.padEnd(40)}${r.startedAt}`)}console.log("")}catch(o){t.fail(_.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),_a=new le.Command("group").description("Group bots/rooms into a shared Claude Code session").requiredOption("--session <id>","Session ID to group under").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").action(async e=>{let t=(0,Se.default)("Grouping bot+room into session...").start();try{await ce.default.post(`${_e}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:e.session},{timeout:1e4}),t.succeed(_.default.green(`Grouped ${e.bot} + ${e.room} into session "${e.session}"`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(_.default.red(`Failed to group: ${n}`)),process.exit(1)}}),Sa=new le.Command("allow").description("Add a user to the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to allow (e.g. @alice:server)").action(async e=>{let t=(0,Se.default)("Adding user to allowlist...").start();try{await ce.default.post(`${_e}/claude-code/allow`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(_.default.green(`Added ${e.user} to allowlist for ${e.bot} in ${e.room}`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(_.default.red(`Failed to add user: ${n}`)),process.exit(1)}}),$a=new le.Command("revoke").description("Remove a user from the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to revoke").action(async e=>{let t=(0,Se.default)("Removing user from allowlist...").start();try{await ce.default.post(`${_e}/claude-code/revoke`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(_.default.green(`Removed ${e.user} from allowlist for ${e.bot} in ${e.room}`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(_.default.red(`Failed to revoke user: ${n}`)),process.exit(1)}}),wr=new le.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(ya).addCommand(wa).addCommand(ba).addCommand(_a).addCommand(Sa).addCommand($a);Ce();async function va(){await Xo(process.argv);let e=new br.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.58"),e.addCommand(xn),e.addCommand(En),e.addCommand(On),e.addCommand(Hn),e.addCommand(gn),e.addCommand(nr),e.addCommand(mr),e.addCommand(xo),e.addCommand(fr),e.addCommand(yr),e.addCommand(wr),e.parse(process.argv)}va().catch(e=>{console.error(e),process.exit(1)});
157
+ Local Sessions:`)),console.log(_.default.dim(" Session".padEnd(25)+"Port".padEnd(8)+"MCP PID".padEnd(10)+"Project".padEnd(40)+"Started")),console.log(_.default.dim(" "+"-".repeat(90)));for(let r of n)console.log(` ${r.sessionId.padEnd(25)}${String(r.port).padEnd(8)}${String(r.mcpPid).padEnd(10)}${r.projectDir.padEnd(40)}${r.startedAt}`)}console.log("")}catch(o){t.fail(_.default.red(`Failed to get status: ${o.message}`)),process.exit(1)}}),Sa=new le.Command("group").description("Group bots/rooms into a shared Claude Code session").requiredOption("--session <id>","Session ID to group under").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").action(async e=>{let t=(0,Se.default)("Grouping bot+room into session...").start();try{await ce.default.post(`${_e}/claude-code/toggle`,{botId:e.bot,roomId:e.room,enabled:!0,sessionId:e.session},{timeout:1e4}),t.succeed(_.default.green(`Grouped ${e.bot} + ${e.room} into session "${e.session}"`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(_.default.red(`Failed to group: ${n}`)),process.exit(1)}}),$a=new le.Command("allow").description("Add a user to the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to allow (e.g. @alice:server)").action(async e=>{let t=(0,Se.default)("Adding user to allowlist...").start();try{await ce.default.post(`${_e}/claude-code/allow`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(_.default.green(`Added ${e.user} to allowlist for ${e.bot} in ${e.room}`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(_.default.red(`Failed to add user: ${n}`)),process.exit(1)}}),va=new le.Command("revoke").description("Remove a user from the Claude Code allowlist for a bot+room").requiredOption("--bot <botId>","Bot ID or username").requiredOption("--room <roomId>","Matrix room ID").requiredOption("--user <userId>","Matrix user ID to revoke").action(async e=>{let t=(0,Se.default)("Removing user from allowlist...").start();try{await ce.default.post(`${_e}/claude-code/revoke`,{botId:e.bot,roomId:e.room,userId:e.user},{timeout:1e4}),t.succeed(_.default.green(`Removed ${e.user} from allowlist for ${e.bot} in ${e.room}`))}catch(o){let n=o.response?.data?.message||o.message||"Unknown error";t.fail(_.default.red(`Failed to revoke user: ${n}`)),process.exit(1)}}),br=new le.Command("claude-code").description("Manage Claude Code sessions (relay Matrix messages to local Claude Code)").addCommand(wa).addCommand(ba).addCommand(_a).addCommand(Sa).addCommand($a).addCommand(va);Ce();async function Ca(){await Xo(process.argv);let e=new _r.Command;e.name("badgerclaw").description("BadgerClaw CLI \u2014 one-click bot provisioning").version("0.2.59"),e.addCommand(Rn),e.addCommand(Pn),e.addCommand(Dn),e.addCommand(Gn),e.addCommand(fn),e.addCommand(rr),e.addCommand(pr),e.addCommand(xo),e.addCommand(hr),e.addCommand(wr),e.addCommand(br),e.parse(process.argv)}Ca().catch(e=>{console.error(e),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "badgerclaw",
3
- "version": "0.2.58",
3
+ "version": "0.2.59",
4
4
  "description": "BadgerClaw CLI — one-click bot provisioning",
5
5
  "main": "dist/index.js",
6
6
  "bin": {