@botmobile/botmobile-openclaw 0.0.10 → 0.0.12

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.

Potentially problematic release.


This version of @botmobile/botmobile-openclaw might be problematic. Click here for more details.

package/INSTALL.md ADDED
@@ -0,0 +1,109 @@
1
+ # BotMobile — OpenClaw Plugin
2
+
3
+ BotMobile is an OpenClaw channel plugin. It connects your OpenClaw gateway to the BotMobile iOS app so you can use your agents from your phone — chat, see live tool activity, manage scheduled tasks, all over a direct WebRTC connection.
4
+
5
+ ## Before installing
6
+
7
+ Ask the user if they'd like to install BotMobile. Briefly explain:
8
+
9
+ - It adds a mobile channel to their OpenClaw setup
10
+ - They'll need the BotMobile iOS app on their iPhone
11
+ - Installation requires a gateway restart (brief downtime)
12
+ - After install, they pair their phone with a code — takes about a minute
13
+
14
+ If the user wants more detail before deciding, here's what to share:
15
+
16
+ **How it works:** The plugin runs inside the gateway and opens a peer-to-peer WebRTC connection to the phone app. Signaling goes through a Cloudflare relay (`botmobile.vantis.ai`), but all actual data (messages, state) flows directly between gateway and phone — nothing is stored in the cloud.
17
+
18
+ **What it installs:** The npm package `@openclaw/botmobile` plus one native dependency (`node-datachannel` for WebRTC). The native binary is a prebuilt download (~5 MB), not compiled from source.
19
+
20
+ **What it can do:** Chat with any of your agents, see which agent is working and what tools it's using in real time, run and manage cron jobs, view conversation history.
21
+
22
+ ## Installation
23
+
24
+ Only proceed after the user confirms they want to install.
25
+
26
+ ### Step 1 — Install the plugin
27
+
28
+ ```bash
29
+ openclaw plugins install @openclaw/botmobile
30
+ ```
31
+
32
+ ### Step 2 — Install native dependencies
33
+
34
+ OpenClaw's plugin installer skips npm lifecycle scripts, so the WebRTC native binary isn't downloaded automatically. Run npm install manually in the plugin directory:
35
+
36
+ ```bash
37
+ cd ~/.openclaw/extensions/botmobile-openclaw && npm install
38
+ ```
39
+
40
+ Verify it worked:
41
+
42
+ ```bash
43
+ ls ~/.openclaw/extensions/botmobile-openclaw/node_modules/node-datachannel/build/Release/node_datachannel.node
44
+ ```
45
+
46
+ ### Step 3 — Restart the gateway
47
+
48
+ ```bash
49
+ openclaw gateway restart
50
+ ```
51
+
52
+ The plugin loads on startup. Tell the user the gateway is restarting and to wait a moment.
53
+
54
+ ### Step 4 — Pair with the phone
55
+
56
+ After the gateway is back, call the `botmobile_pair` tool (no parameters).
57
+
58
+ It returns:
59
+ - `pairingCode` — e.g. `ABCD-1234`
60
+ - `deepLink` — a `botmobile://...` URL
61
+
62
+ Send the user:
63
+
64
+ > BotMobile is ready to pair! Open the BotMobile app and enter code: **ABCD-1234**
65
+ >
66
+ > Or tap this link to pair automatically: botmobile://...
67
+ >
68
+ > Need the app? Search "BotMobile" on the App Store.
69
+
70
+ The plugin waits in the background. When the user pairs in the app, config is saved and the channel connects automatically.
71
+
72
+ ## Troubleshooting
73
+
74
+ **"node-datachannel native binary is missing"** — `cd ~/.openclaw/extensions/botmobile-openclaw && npm install`, then restart gateway.
75
+
76
+ **Plugin not loading** — `openclaw plugins list`. If disabled: `openclaw plugins enable botmobile-openclaw`, then restart.
77
+
78
+ **Phone not connecting** — Check gateway logs for `[botmobile] signaling connected`. Try re-pairing via `botmobile_pair`. Ensure phone has internet and app is open.
79
+
80
+ ## Technical reference
81
+
82
+ <details>
83
+ <summary>Architecture and data flow</summary>
84
+
85
+ ```
86
+ iPhone app ←→ Cloudflare DO (signaling) ←→ WebRTC datachannel ←→ plugin (gateway)
87
+ ```
88
+
89
+ **Inbound:** Phone → datachannel → monitor → OC channel pipeline → agent.
90
+ **Outbound:** Agent reply → channel sendText → wsRelay → datachannel → phone.
91
+
92
+ Config stored in `~/.openclaw/openclaw.json` under `channels.botmobile`.
93
+
94
+ Key dependencies: `node-datachannel` (WebRTC native addon), `msgpackr` (wire protocol), `ws` (signaling), `qrcode-terminal` (CLI pairing).
95
+ </details>
96
+
97
+ <details>
98
+ <summary>Source files</summary>
99
+
100
+ | File | Role |
101
+ |------|------|
102
+ | `index.ts` | Plugin entry. Registers channel, `botmobile_pair` tool, and hooks. |
103
+ | `src/channel.ts` | Channel plugin. Outbound messaging, account config, reload on config change. |
104
+ | `src/monitor.ts` | Core runtime. WebRTC transport, message relay, agent/cron state sync. |
105
+ | `src/webrtc.ts` | WebRTC layer. Signaling, ICE/SDP, datachannel, reconnection. |
106
+ | `src/pairing.ts` | Pairing API. Calls worker, builds deep links, waits for phone via WS. |
107
+ | `src/cron-bridge.ts` | Cron operations. Reads disk, writes via gateway WS RPC. |
108
+ | `src/state-sync.ts` | Binary wire protocol (msgpack) for datachannel messages. |
109
+ </details>
package/dist/index.js CHANGED
@@ -1,20 +1,20 @@
1
- import{createRequire as h5}from"node:module";var S5=Object.create;var{getPrototypeOf:j5,defineProperty:b0,getOwnPropertyNames:C5}=Object;var k5=Object.prototype.hasOwnProperty;var A5=(Z,$,Q)=>{Q=Z!=null?S5(j5(Z)):{};let X=$||!Z||!Z.__esModule?b0(Q,"default",{value:Z,enumerable:!0}):Q;for(let Y of C5(Z))if(!k5.call(X,Y))b0(X,Y,{get:()=>Z[Y],enumerable:!0});return X};var x5=(Z,$)=>{for(var Q in $)b0(Z,Q,{get:$[Q],enumerable:!0,configurable:!0,set:(X)=>$[Q]=()=>X})};var KZ=(Z,$)=>()=>(Z&&($=Z(Z=0)),$);var T5=h5(import.meta.url);function A3(Z){f0=Z}function J0(){if(!f0)throw Error("BotMobile runtime not initialized");return f0}var f0=null;import f5 from"node:fs";import I0 from"node:os";import oZ from"node:path";function TZ(Z){if(typeof Z!=="string")return;let $=Z.trim();return $.length>0?$:void 0}function nZ(Z){return(TZ(Z)??"main").toLowerCase()}function y0(Z){let $=Z.agents?.list;if(!Array.isArray($))return[];return $.filter((Q)=>!!Q&&typeof Q==="object")}function y5(Z){let $=y0(Z);if($.length===0)return"main";let Q=$.find((X)=>X.default===!0);return nZ((Q??$[0])?.id)}function h3(Z){if(Z.startsWith("~"))return oZ.resolve(Z.replace(/^~/,I0.homedir()));return oZ.resolve(Z)}function u5(Z,$){let Q=nZ($),Y=y0(Z).find((J)=>nZ(J.id)===Q),H=TZ(Y?.workspace);if(H)return h3(H);let V=y5(Z);if(Q===V){let J=TZ(Z.agents?.defaults?.workspace);if(J)return h3(J);return oZ.join(I0.homedir(),".openclaw","workspace")}return oZ.join(I0.homedir(),".openclaw",`workspace-${Q}`)}function T3(Z,$){let Q=Z.split(/\r?\n/);for(let X=0;X<Q.length;X++){let H=Q[X].replace(/\*\*/g,"").trim().match(new RegExp(`^(?:[-*]\\s*)?${$}\\s*:\\s*(.*?)\\s*$`,"i"));if(!H)continue;let V=H[1]?.trim();if(!V&&X+1<Q.length)V=Q[X+1].replace(/\*\*/g,"").trim();if(!V)continue;let J=V.replace(/^["'`]|["'`]$/g,"").trim();if(!J)continue;return J}return}function v5(Z){let $=Date.now(),Q=x3.get(Z);if(Q&&$-Q.loadedAt<I5)return{name:Q.name,emoji:Q.emoji};let X=oZ.join(Z,"IDENTITY.md"),Y,H;try{let V=f5.readFileSync(X,"utf8");Y=T3(V,"name"),H=T3(V,"emoji")}catch{Y=void 0,H=void 0}return x3.set(Z,{loadedAt:$,name:Y,emoji:H}),{name:Y,emoji:H}}function bZ(Z,$){let Q=nZ($),Y=y0(Z).find((O)=>nZ(O.id)===Q),H=TZ(Y?.identity?.emoji),V=TZ(Y?.identity?.name),J=u5(Z,Q),q=v5(J);if(V)return{name:V,emoji:H??q.emoji,source:"identity-config",emojiSource:H?"identity-config":q.emoji?"identity-file":void 0};let K=q.name;if(K)return{name:K,emoji:H??q.emoji,source:"identity-file",emojiSource:H?"identity-config":q.emoji?"identity-file":void 0};let B=TZ(Y?.name);if(B)return{name:B,emoji:H??q.emoji,source:"config-name",emojiSource:H?"identity-config":q.emoji?"identity-file":void 0};return{name:Q||"Assistant",emoji:H??q.emoji,source:"agent-id",emojiSource:H?"identity-config":q.emoji?"identity-file":void 0}}var x3,I5=30000;var q0=KZ(()=>{x3=new Map});function R(Z){let $=Z.trim();if(!$)return Z;if(m5.test($))return $.toUpperCase();return $}var m5;var K0=KZ(()=>{m5=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i});import I3 from"node:fs";import aZ from"node:path";import b3 from"node:os";import{randomUUID as O0}from"node:crypto";import tZ from"ws";function u3(Z){let $=Z.cron?.store;if(typeof $==="string"&&$.trim()){let Q=$.trim();if(Q.startsWith("~"))return aZ.resolve(Q.replace("~",b3.homedir()));return aZ.resolve(Q)}return aZ.join(b3.homedir(),".openclaw","cron","jobs.json")}function c5(Z,$){return aZ.join(aZ.dirname(Z),"runs",`${$}.jsonl`)}function u0(Z){let $=Z.gateway?.port;if(typeof $==="number"&&Number.isFinite($)&&$>0)return $;return g5}function v0(Z){let $=Z.gateway?.auth?.token;return typeof $==="string"&&$.trim()?$.trim():void 0}function m0(Z){return typeof Z==="object"&&Z!==null}function l5(Z){if(!m0(Z))return!1;return Z.type==="res"&&typeof Z.id==="string"&&typeof Z.ok==="boolean"}function f3(Z){if(!m0(Z))return!1;return Z.type==="event"&&typeof Z.event==="string"}function d5(Z){if(!m0(Z))return null;let{jobId:$,action:Q}=Z;if(typeof $!=="string"||!$.trim())return null;if(Q!=="added"&&Q!=="updated"&&Q!=="removed"&&Q!=="started"&&Q!=="finished")return null;let X={jobId:$,action:Q};if(typeof Z.runAtMs==="number"&&Number.isFinite(Z.runAtMs))X.runAtMs=Z.runAtMs;if(typeof Z.durationMs==="number"&&Number.isFinite(Z.durationMs))X.durationMs=Z.durationMs;if(Z.status==="ok"||Z.status==="error"||Z.status==="skipped")X.status=Z.status;if(typeof Z.error==="string")X.error=Z.error;if(typeof Z.summary==="string")X.summary=Z.summary;if(typeof Z.sessionId==="string")X.sessionId=Z.sessionId;if(typeof Z.sessionKey==="string")X.sessionKey=Z.sessionKey;if(typeof Z.nextRunAtMs==="number"&&Number.isFinite(Z.nextRunAtMs))X.nextRunAtMs=Z.nextRunAtMs;return X}class v3{cfg;tag;ws=null;reconnectTimer=null;reconnectDelayMs=1000;connectRequestId=null;stopped=!1;connected=!1;pending=new Map;cronListeners=new Set;constructor(Z,$){this.cfg=Z;this.tag=$}start(){this.stopped=!1,this.ensureConnected()}stop(){if(this.stopped=!0,this.connected=!1,this.connectRequestId=null,this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;let Z=this.ws;if(this.ws=null,Z)try{Z.close()}catch{}this.failPending("gateway bridge stopped")}isConnected(){return this.connected&&this.ws!==null&&this.ws.readyState===tZ.OPEN}listenerCount(){return this.cronListeners.size}addCronListener(Z){return this.cronListeners.add(Z),this.start(),()=>{this.cronListeners.delete(Z)}}async request(Z,$){let Q=this.ws;if(!this.isConnected()||!Q)return{ok:!1,error:"gateway bridge not connected"};let X=O0(),H=JSON.stringify({type:"req",id:X,method:Z,params:$});return await new Promise((V)=>{let J=setTimeout(()=>{this.pending.delete(X),V({ok:!1,error:`gateway ${Z} timeout after ${B0}ms`})},B0);this.pending.set(X,{resolve:V,timeout:J});try{Q.send(H)}catch(q){this.pending.delete(X),clearTimeout(J),V({ok:!1,error:`gateway WS send failed: ${String(q)}`})}})}ensureConnected(){if(this.stopped)return;if(this.ws&&this.ws.readyState===tZ.OPEN)return;if(this.ws&&this.ws.readyState===tZ.CONNECTING)return;if(this.reconnectTimer)return;let Z=u0(this.cfg),$=v0(this.cfg),Q=`ws://127.0.0.1:${Z}`,X=new tZ(Q,{maxPayload:4194304});this.ws=X,this.connected=!1;let Y=!1,H=()=>{if(Y)return;Y=!0,this.connectRequestId=O0();let V={minProtocol:3,maxProtocol:3,client:{id:"gateway-client",version:"dev",platform:process.platform,mode:"backend"},caps:[],role:"operator",scopes:["operator.admin"]};if($)V.auth={token:$};try{X.send(JSON.stringify({type:"req",id:this.connectRequestId,method:"connect",params:V}))}catch(J){console.error(`${this.tag} bridge connect send failed: ${String(J)}`)}};X.on("open",()=>{H()}),X.on("message",(V)=>{try{let J=JSON.parse(String(V));if(l5(J)){if(J.id===this.connectRequestId){if(!J.ok){this.connected=!1,console.error(`${this.tag} bridge connect failed: ${J.error?.message??"unknown"}`);try{X.close()}catch{}return}this.connected=!0,this.reconnectDelayMs=1000;return}let q=this.pending.get(J.id);if(q)if(this.pending.delete(J.id),clearTimeout(q.timeout),J.ok)q.resolve({ok:!0,payload:J.payload});else q.resolve({ok:!1,error:J.error?.message??"unknown error"});return}if(f3(J)&&J.event==="cron"){let q=d5(J.payload);if(!q)return;for(let K of this.cronListeners)try{K(q)}catch(B){console.error(`${this.tag} cron listener failed: ${String(B)}`)}return}if(f3(J)&&J.event==="connect.challenge"){if(!Y)H()}}catch{}}),X.on("error",(V)=>{console.error(`${this.tag} bridge WS error: ${String(V)}`)}),X.on("close",()=>{if(this.ws===X)this.ws=null;this.connected=!1,this.connectRequestId=null,this.failPending("gateway connection closed"),this.scheduleReconnect()})}scheduleReconnect(){if(this.stopped)return;if(this.reconnectTimer)return;if(this.cronListeners.size===0)return;let Z=this.reconnectDelayMs;this.reconnectDelayMs=Math.min(this.reconnectDelayMs*2,p5),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.ensureConnected()},Z)}failPending(Z){for(let[$,Q]of this.pending)this.pending.delete($),clearTimeout(Q.timeout),Q.resolve({ok:!1,error:Z})}}function m3(Z){return`${u0(Z)}|${v0(Z)??""}`}function i5(Z){let $=m3(Z);if(t&&L0===$)return t;if(t)t.stop();return t=new v3(Z,y3),L0=$,t}function g3(Z,$){let X=i5(Z).addCronListener($);return()=>{if(X(),t&&t.listenerCount()===0)t.stop(),t=null,L0=null}}async function g0(Z,$,Q){let X=m3(Z);if(t&&L0===X&&t.isConnected()){let Y=await t.request($,Q);if(Y.ok||Y.error!=="gateway bridge not connected")return Y}return await r5(Z,$,Q)}async function r5(Z,$,Q){let X=u0(Z),Y=v0(Z),H=`ws://127.0.0.1:${X}`;return new Promise((V)=>{let J=!1,q=(N)=>{if(J)return;J=!0,clearTimeout(K);try{B.close()}catch{}V(N)},K=setTimeout(()=>{q({ok:!1,error:`gateway RPC timeout after ${B0}ms`})},B0),B=new tZ(H,{maxPayload:4194304}),O=null,L=null,D=!1,U=null,z=(N)=>{if(D)return;if(D=!0,U)clearTimeout(U),U=null;O=O0();let G={minProtocol:3,maxProtocol:3,client:{id:"gateway-client",version:"dev",platform:process.platform,mode:"backend"},caps:[],role:"operator",scopes:["operator.admin"]};if(Y)G.auth={token:Y};B.send(JSON.stringify({type:"req",id:O,method:"connect",params:G}))};B.on("open",()=>{U=setTimeout(()=>z(),750)}),B.on("message",(N)=>{try{let G=JSON.parse(String(N));if(G.type==="event"){if(G.event==="connect.challenge"){let T=G.payload?.nonce;z(typeof T==="string"?T:void 0)}return}if(G.type==="res"&&G.id===O){if(!G.ok){q({ok:!1,error:`gateway connect failed: ${G.error?.message??"unknown"}`});return}L=O0(),B.send(JSON.stringify({type:"req",id:L,method:$,params:Q}));return}if(G.type==="res"&&G.id===L){if(G.ok)q({ok:!0,payload:G.payload});else q({ok:!1,error:G.error?.message??"unknown error"});return}}catch{}}),B.on("error",(N)=>{q({ok:!1,error:`gateway WS error: ${String(N)}`})}),B.on("close",()=>{q({ok:!1,error:"gateway WS closed unexpectedly"})})})}function p0(Z){let $=u3(Z);try{let Q=I3.readFileSync($,"utf-8");return JSON.parse(Q)?.jobs??[]}catch(Q){return console.error(`${y3} failed to read cron store at ${$}: ${String(Q)}`),[]}}function p3(Z,$,Q=20){let X=u3(Z),Y=c5(X,$);try{let H=I3.readFileSync(Y,"utf-8");if(!H.trim())return[];let V=H.split(`
2
- `),J=[];for(let q=V.length-1;q>=0&&J.length<Q;q--){let K=V[q]?.trim();if(!K)continue;try{let B=JSON.parse(K);if(B?.action==="finished"&&typeof B.ts==="number")J.push({ts:B.ts,jobId:B.jobId??$,action:B.action,status:B.status,error:B.error,summary:B.summary,durationMs:B.durationMs})}catch{}}return J}catch{return[]}}async function c3(Z,$){let Q=await g0(Z,"cron.run",{id:$,mode:"force"});if(!Q.ok)return{ok:!1,error:Q.error};return{ok:!0}}async function l3(Z,$,Q){let X=await g0(Z,"cron.update",{id:$,patch:{enabled:Q}});if(!X.ok)return{ok:!1,error:X.error};return{ok:!0}}async function d3(Z,$){let Q=await g0(Z,"cron.add",$);if(!Q.ok)return{ok:!1,error:Q.error};return{ok:!0}}var y3="[botmobile:cron]",g5=18789,B0=15000,p5=30000,t=null,L0=null;var i3=()=>{};function h(Z){for(let $ of o5)try{$(Z)}catch{}}function M(){return Date.now()}function I(Z,$=M()){if(typeof Z==="number"&&Number.isFinite(Z)&&Z>0)return Math.floor(Z);return Math.floor($)}function r3(Z){if(!Z)return;let $=Z.trim();if(!$)return;if($.startsWith("conversation:"))return;if($.toLowerCase()==="conversation")return;return R($)}function d0(Z){if(!Z)return;let $=Z.trim().toLowerCase();return $.length>0?$:void 0}function U0(Z){let $=Z.trim();if(!$.toLowerCase().startsWith("cron:"))return;return d0($.slice(5))}function n5(Z,$){if(Z?.trim().toLowerCase()==="cron")return"cron";return U0($)?"cron":void 0}function PZ(Z){if(!Z)return;let $=Z.trim();return $.length>0?$:void 0}function c0(Z){return Z.id.startsWith("conversation:")&&Z.messageOrder.length===0}function t3(Z){let $=I(Z,M());return OZ=Math.max(OZ+1,$),OZ}function WZ(Z){let $=++EZ;return t3(Z),$}function i0(Z){if(!Z)return;return{...Z,skills:Z.skills?[...Z.skills]:void 0,skillDetails:Z.skillDetails?Z.skillDetails.map(($)=>({...$})):void 0,toolsAllow:Z.toolsAllow?[...Z.toolsAllow]:void 0,toolsDeny:Z.toolsDeny?[...Z.toolsDeny]:void 0}}function t5(Z){return{...Z,details:i0(Z.details),usage:{...Z.usage}}}function a5(Z){return{...Z,schedule:Z.schedule?{...Z.schedule}:void 0}}function r0(Z){return{...Z}}function e5(Z){return{...Z}}function Z6(Z){return{id:`conversation:${Z}`,name:n3}}function l0(Z){let $=typeof Z.id==="string"?Z.id.trim().toLowerCase():"",Q=typeof Z.name==="string"?Z.name.trim().toLowerCase():"";if(!$)return!0;if($==="conversation"||$.startsWith("conversation:"))return!0;if(!Q)return!0;return Q===n3.toLowerCase()||Q==="conversation"}function a3(Z){return{isAgentActive:!1,isComposing:!1,lastUpdated:Z}}function $6(Z,$){let Q=r.get(Z);if(!Q)return null;r.delete(Z),Q.id=$;for(let X of Q.messages.values())X.conversationId=$;r.set($,Q);for(let[X,Y]of YZ)if(Y===Z)YZ.set(X,$);return Q}function Q6(Z){for(let $ of r.keys())if(R($)===Z)return $;return null}function a(Z,$){let Q=R(Z),X=r.get(Q);if(X)return X;let Y=Q6(Q);if(Y&&Y!==Q){let q=$6(Y,Q);if(q)return q}let H=I($,M()),V=U0(Q),J={id:Q,kind:V?"cron":void 0,cronJobId:V,cronName:void 0,cronAgentId:void 0,cronAgentName:void 0,cronAgentEmoji:void 0,agent:Z6(Q),createdAt:H,updatedAt:H,revision:0,lastMessageRevision:0,activity:a3(H),messages:new Map,messageOrder:[]};return J.revision=WZ(H),r.set(Q,J),J}function BZ(Z,$){let Q=I($,M());Z.updatedAt=Math.max(Z.updatedAt,Q)}function HZ(Z,$,Q){let X=WZ($);if(Z.revision=Math.max(Z.revision,X),Q?.messageChanged)Z.lastMessageRevision=Math.max(Z.lastMessageRevision,X);return X}function X6(Z){for(let $ of Z.messages.values())if($.isStreaming)return!0;return!1}function XZ(Z,$,Q){let X=I(Q,M()),Y=Z.activity,H=Y.activeAgentId,V=Object.prototype.hasOwnProperty.call($,"activeAgentId"),J=Object.prototype.hasOwnProperty.call($,"activeTool"),q={isAgentActive:$.isAgentActive??Y.isAgentActive,isComposing:$.isComposing??Y.isComposing,activeAgentId:V?$.activeAgentId:Y.activeAgentId,activeTool:J?$.activeTool:Y.activeTool,lastUpdated:Math.max(Y.lastUpdated,X)};if(!q.isAgentActive&&!q.isComposing)q.activeAgentId=void 0,q.activeTool=void 0;else if(!q.isAgentActive)q.activeTool=void 0;if(!(q.isAgentActive!==Y.isAgentActive||q.isComposing!==Y.isComposing||q.activeAgentId!==Y.activeAgentId||q.activeTool!==Y.activeTool)){if(q.lastUpdated>Y.lastUpdated)Y.lastUpdated=q.lastUpdated;if(q.isAgentActive&&q.activeAgentId)YZ.set(q.activeAgentId,Z.id);return!1}if(Z.activity=q,H&&YZ.get(H)===Z.id&&q.activeAgentId!==H)YZ.delete(H);if(q.isAgentActive&&q.activeAgentId)YZ.set(q.activeAgentId,Z.id);return BZ(Z,X),HZ(Z,X),!0}function eZ(Z,$,Q){let X=I($,M()),Y=Q?R(Q):void 0,H=!1,V=YZ.get(Z);if(V&&V!==Y){let J=r.get(V);if(J)H=XZ(J,{isAgentActive:!1,isComposing:!1,activeAgentId:void 0,activeTool:void 0},X)||H}for(let[J,q]of r){if(J===V)continue;if(J===Y)continue;if(q.activity.activeAgentId!==Z)continue;H=XZ(q,{isAgentActive:!1,isComposing:!1,activeAgentId:void 0,activeTool:void 0},X)||H}if(Y)YZ.set(Z,Y);else YZ.delete(Z);return H}function Y6(Z){while(Z.messageOrder.length>s5){let $=Z.messageOrder.shift();if(!$)break;Z.messages.delete($)}}function fZ(Z,$,Q){let X=I($.timestamp,M()),Y=Z.messages.get($.id);if(!Y){let V=HZ(Z,X,{messageChanged:!0});Z.messages.set($.id,r0({...$,timestamp:X,revision:V})),Z.messageOrder.push($.id),Y6(Z),BZ(Z,X);return}if(Q==="append")Y.content+=$.content,Y.timestamp=X,Y.isStreaming=$.isStreaming??Y.isStreaming;else Y.content=$.content,Y.role=$.role,Y.timestamp=X,Y.isStreaming=$.isStreaming;let H=HZ(Z,Y.timestamp,{messageChanged:!0});Y.revision=H,BZ(Z,Y.timestamp)}function H6(Z){let $=[];for(let Q of Z.messageOrder){let X=Z.messages.get(Q);if(!X)continue;$.push(r0(X))}return $.sort((Q,X)=>{if(Q.timestamp===X.timestamp)return Q.id.localeCompare(X.id);return Q.timestamp-X.timestamp}),$}function D0(Z,$){let Q=$?.sinceTimestampMs,X=typeof $?.lastMessageRevision==="number"&&Number.isFinite($.lastMessageRevision)?Math.max(0,Math.floor($.lastMessageRevision)):0,Y=H6(Z).filter((H)=>{if(X>0){let V=typeof H.revision==="number"&&Number.isFinite(H.revision)?Math.max(0,Math.floor(H.revision)):0;if(V>X)return!0;if(V>0)return!1}if(!Q||!Number.isFinite(Q)||Q<=0)return!0;return H.timestamp>Q});return{id:Z.id,kind:Z.kind,cronJobId:Z.cronJobId,cronName:Z.cronName,cronAgentId:Z.cronAgentId,cronAgentName:Z.cronAgentName,cronAgentEmoji:Z.cronAgentEmoji,agent:{...Z.agent},createdAt:Z.createdAt,updatedAt:Z.updatedAt,revision:Z.revision,lastMessageRevision:Z.lastMessageRevision,activity:e5(Z.activity),messages:Y}}function e3(Z){let $=Number.isFinite(Z.sessionTokensIn)?Z.sessionTokensIn:0,Q=Number.isFinite(Z.sessionTokensOut)?Z.sessionTokensOut:0,X=I(Z.lastActivityAt,M()),Y=Z.status==="working";return{id:Z.agentId,name:Z.name||Z.agentId,emoji:Z.emoji,color:Z.color,details:i0(Z.details),queue:Y?1:0,lastUpdated:X,usage:{mode:"tokens",value:Math.max(0,$+Q)},isRunning:Y,currentTask:Z.activeTool}}function Z4(Z,$){let Q=I($??Z.lastRunAt??Z.nextRunAt,M());return{id:Z.id,name:Z.name,enabled:Z.enabled,isRunning:Z.isRunning,lastUpdated:Q,agentId:Z.agentId,agentName:Z.agentName,agentEmoji:Z.agentEmoji,schedule:Z.schedule?{...Z.schedule}:void 0,nextRunAt:Z.nextRunAt,lastRunAt:Z.lastRunAt,lastRunStatus:Z.lastRunStatus,lastRunSummary:Z.lastRunSummary}}function Z0(Z){if(jZ.size>0)return[...jZ.values()].map(t5);if(!Z||Z.length===0)return[];return Z.map(($)=>e3($))}function $0(Z){if(_Z.size>0)return[..._Z.values()].map(a5);if(!Z||Z.length===0)return[];return Z.map(($)=>Z4($))}function s3(Z){let $=[...r.values()].filter((Y)=>!c0(Y)).sort((Y,H)=>H.updatedAt-Y.updatedAt).map((Y)=>D0(Y)),Q=Z0(Z?.fallbackAgents),X=$0(Z?.fallbackCronJobs);return{timestamp:OZ,stateBornAt:GZ,globalRevision:EZ,conversations:$,agents:Q,cronJobs:X}}function $4(){r.clear(),jZ.clear(),_Z.clear(),YZ.clear(),GZ=M(),OZ=GZ,EZ=0}function Q4(Z){let $=0;for(let Q of Z){let X=R(Q.id),Y=U0(X),H=n5(Q.kind,X),V=d0(Q.cronJobId)??Y,J=PZ(Q.cronName),q=PZ(Q.cronAgentId),K=PZ(Q.cronAgentName),B=PZ(Q.cronAgentEmoji),O=new Map,L=[],D=0;for(let G of Q.messages){let T=I(G.timestamp,M()),A=WZ(T);O.set(G.id,r0({...G,conversationId:X,timestamp:T,revision:A})),L.push(G.id),$=Math.max($,T),D=A}let U=I(Q.createdAt,M()),z=I(Q.updatedAt,U),N=D>0?D:WZ(z);r.set(X,{id:X,kind:H,cronJobId:V,cronName:J,cronAgentId:q,cronAgentName:K,cronAgentEmoji:B,agent:{...Q.agent},createdAt:U,updatedAt:z,revision:N,lastMessageRevision:D,activity:a3(z),messages:O,messageOrder:L}),$=Math.max($,z)}if($>0)t3($)}function F0(Z,$,Q){let X=R(Z),Y=I(Q,M()),H=a(X,Y);H.agent={id:$.id||H.agent.id,name:$.name||H.agent.name,emoji:$.emoji??H.agent.emoji},BZ(H,Y),HZ(H,Y),h("conversations")}function s0(Z,$){let Q=R(Z.conversationId),X=I($,M()),Y=a(Q,X),H=U0(Q),V=d0(Z.cronJobId)??H,J=Y.kind??(V?"cron":void 0),q=PZ(Z.cronName)??Y.cronName,K=PZ(Z.cronAgentId)??Y.cronAgentId,B=PZ(Z.cronAgentName)??Y.cronAgentName,O=PZ(Z.cronAgentEmoji)??Y.cronAgentEmoji,L={...Y.agent};if(Y.kind==="cron"||J==="cron"){if(q&&l0(Y.agent))L.name=q;if(O&&!L.emoji)L.emoji=O}if(!(Y.kind!==J||Y.cronJobId!==V||Y.cronName!==q||Y.cronAgentId!==K||Y.cronAgentName!==B||Y.cronAgentEmoji!==O||Y.agent.id!==L.id||Y.agent.name!==L.name||Y.agent.emoji!==L.emoji))return;Y.kind=J,Y.cronJobId=V,Y.cronName=q,Y.cronAgentId=K,Y.cronAgentName=B,Y.cronAgentEmoji=O,Y.agent=L,BZ(Y,X),HZ(Y,X),h("conversations")}function X4(Z){if(Z.from!=="user")return;let $=R(Z.conversationId),Q=I(Z.timestamp,M()),X=a($,Q);fZ(X,{id:Z.id,conversationId:$,role:"user",content:Z.body,timestamp:Q,isStreaming:!1},"replace"),h("conversations")}function Y4(Z){switch(Z.type){case"conversation_list":{for(let $ of Z.conversations){let Q=R($.id),X=I($.lastActivity,M()),Y=a(Q,$.createdAt);Y.createdAt=Math.min(Y.createdAt,I($.createdAt,Y.createdAt)),Y.updatedAt=Math.max(Y.updatedAt,X);let H=$.name.trim();if(H.length>0)Y.agent={id:Y.agent.id,name:H,emoji:Y.agent.emoji};HZ(Y,X)}h("conversations");return}case"message":{let $=R(Z.conversationId),Q=I(Z.timestamp,M()),X=a($,Q);if(fZ(X,{id:Z.id,conversationId:$,role:Z.from==="user"?"user":"bot",content:Z.body,timestamp:Q,isStreaming:!1},"replace"),Z.from==="bot")XZ(X,{isComposing:!1,activeTool:void 0},Q);h("conversations");return}case"stream_start":{let $=R(Z.conversationId),Q=M(),X=a($,Q),Y=X.agent.id.startsWith("conversation:")?void 0:X.agent.id;XZ(X,{isAgentActive:!0,isComposing:!0,activeAgentId:Y},Q);let H=X.messages.get(Z.messageId);if(H)H.isStreaming=!0,H.timestamp=Q,H.role="bot",H.revision=HZ(X,Q,{messageChanged:!0}),BZ(X,Q);else fZ(X,{id:Z.messageId,conversationId:$,role:"bot",content:"",timestamp:Q,isStreaming:!0},"replace");h("conversations");return}case"stream_token":{let $=R(Z.conversationId),Q=M(),X=a($,Q),Y=X.agent.id.startsWith("conversation:")?void 0:X.agent.id;XZ(X,{isAgentActive:!0,isComposing:!0,activeAgentId:Y},Q),fZ(X,{id:Z.messageId,conversationId:$,role:"bot",content:Z.token,timestamp:Q,isStreaming:!0},"append"),h("conversations");return}case"stream_end":{let $=R(Z.conversationId),Q=M(),X=a($,Q);XZ(X,{isAgentActive:!1,isComposing:!1,activeTool:void 0},Q);let Y=X.messages.get(Z.messageId);if(Y){if(Z.body.trim().length>0)Y.content=Z.body;Y.isStreaming=!1,Y.timestamp=Q,Y.revision=HZ(X,Q,{messageChanged:!0}),BZ(X,Q)}else fZ(X,{id:Z.messageId,conversationId:$,role:"bot",content:Z.body,timestamp:Q,isStreaming:!1},"replace");h("conversations");return}case"composing":{if(Z.from!=="bot")return;let $=R(Z.conversationId),Q=M(),X=a($,Q),Y=X.agent.id.startsWith("conversation:")?void 0:X.agent.id;XZ(X,{isAgentActive:!0,isComposing:!0,activeAgentId:Y},Q),h("conversations");return}case"tool_status":{let $=R(Z.conversationId),Q=M(),X=a($,Q);if(Z.status==="running"){let Y=X.agent.id.startsWith("conversation:")?void 0:X.agent.id;XZ(X,{isAgentActive:!0,isComposing:!1,activeAgentId:Y,activeTool:Z.tool},Q)}else XZ(X,{isAgentActive:X6(X),isComposing:!1,activeTool:void 0},Q);h("conversations");return}case"agent_list":{let $=!1,Q=new Set;jZ.clear();for(let Y of Z.agents){Q.add(Y.agentId),jZ.set(Y.agentId,e3(Y));let H=I(Y.lastActivityAt,M()),V=r3(Y.activeConversationId);if(Y.status==="working"&&V){$=eZ(Y.agentId,H,V)||$;let J=a(V,H);J.agent={id:Y.agentId||J.agent.id,name:Y.name||J.agent.name,emoji:Y.emoji??J.agent.emoji},$=XZ(J,{isAgentActive:!0,isComposing:J.activity.isComposing,activeAgentId:Y.agentId,activeTool:Y.activeTool},H)||$}else $=eZ(Y.agentId,H)||$}let X=M();for(let Y of Array.from(YZ.keys())){if(Q.has(Y))continue;$=eZ(Y,X)||$}if(WZ(M()),h("agents"),$)h("conversations");return}case"agent_status":{let $=M(),Q=jZ.get(Z.agentId)??{id:Z.agentId,name:Z.agentId,queue:0,lastUpdated:$,usage:{mode:"tokens",value:0},isRunning:Z.status==="working"},X={...Q,color:Z.color??Q.color,details:Z.details?i0(Z.details):Q.details,queue:Z.status==="working"?1:0,lastUpdated:I(Z.lastActivityAt,$),usage:{mode:"tokens",value:typeof Z.sessionTokensIn==="number"||typeof Z.sessionTokensOut==="number"?Math.max(0,(Z.sessionTokensIn??0)+(Z.sessionTokensOut??0)):Q.usage.value},isRunning:Z.status==="working",currentTask:Z.activeTool};jZ.set(Z.agentId,X);let Y=!1,H=Z.status==="working"?r3(Z.activeConversationId):void 0;if(H){Y=eZ(Z.agentId,X.lastUpdated,H)||Y;let V=a(H,X.lastUpdated);V.agent={id:Z.agentId||V.agent.id,name:X.name||V.agent.name,emoji:X.emoji??V.agent.emoji},Y=XZ(V,{isAgentActive:!0,isComposing:V.activity.isComposing,activeAgentId:Z.agentId,activeTool:Z.activeTool},X.lastUpdated)||Y}else Y=eZ(Z.agentId,X.lastUpdated)||Y;if(WZ(X.lastUpdated),h("agents"),Y)h("conversations");return}case"cron_list":{_Z.clear();let $=M();for(let Q of Z.jobs)_Z.set(Q.id,Z4(Q,$));WZ($),h("cronJobs");return}case"cron_run_started":{let $=M(),Q=_Z.get(Z.jobId)??{id:Z.jobId,name:Z.jobId,enabled:!0,isRunning:!1,lastUpdated:$};_Z.set(Z.jobId,{...Q,isRunning:!0,lastUpdated:$}),WZ($),h("cronJobs");return}case"cron_run_finished":{let $=M(),Q=_Z.get(Z.jobId)??{id:Z.jobId,name:Z.jobId,enabled:!0,isRunning:!1,lastUpdated:$};_Z.set(Z.jobId,{...Q,isRunning:!1,lastRunAt:$,lastRunStatus:Z.status,lastRunSummary:Z.summary,lastUpdated:$}),WZ($),h("cronJobs");return}default:return}}function o3(Z){return Z.startsWith("t:")}function H4(Z){let $=R(Z.conversationId),{role:Q,content:X,timestamp:Y,stableId:H}=Z,V=I(Y,M()),J=a($,V),q=o3(H),K=!1;if(Z.agent){let L=l0(J.agent),D=l0(Z.agent),U=typeof Z.agent.id==="string"&&Z.agent.id.trim().length>0&&Z.agent.id===J.agent.id;if(L||U||!D&&!J.agent.emoji&&!!Z.agent.emoji){let z={id:Z.agent.id||J.agent.id,name:Z.agent.name||J.agent.name,emoji:Z.agent.emoji??J.agent.emoji};if(K=z.id!==J.agent.id||z.name!==J.agent.name||z.emoji!==J.agent.emoji,K)J.agent=z,BZ(J,V),HZ(J,V)}}if(J.messages.has(H)){if(K)h("conversations");return!1}let B=J.messageOrder,O=Math.max(0,B.length-J6);for(let L=B.length-1;L>=O;L--){let D=J.messages.get(B[L]);if(!D)continue;if(D.role!==Q)continue;let U=D.content===X||X.startsWith(D.content)||D.content.startsWith(X);if(Q==="bot"&&q&&!o3(D.id)&&V<=D.timestamp&&U){if(!D.isStreaming&&X.length>D.content.length)D.content=X,D.timestamp=Math.max(D.timestamp,V),D.revision=HZ(J,D.timestamp,{messageChanged:!0}),BZ(J,D.timestamp),h("conversations");else if(K)h("conversations");return!1}if(Math.abs(D.timestamp-V)>V6)continue;if(U){if(!D.isStreaming&&X.length>D.content.length)D.content=X,D.timestamp=V,D.revision=HZ(J,V,{messageChanged:!0}),BZ(J,V),h("conversations");else if(K)h("conversations");return!1}}return fZ(J,{id:H,conversationId:$,role:Q,content:X,timestamp:V,isStreaming:!1},"replace"),h("conversations"),!0}function o0(Z){let $=R(Z),Q=r.get($);if(!Q)return null;return D0(Q)}function q6(Z){let $=new Map;if(!Array.isArray(Z))return $;for(let Q of Z){if(!Q||typeof Q.id!=="string"||Q.id.length===0)continue;let X=R(Q.id),Y=typeof Q.conversationRevision==="number"&&Number.isFinite(Q.conversationRevision)?Math.max(0,Math.floor(Q.conversationRevision)):0,H=typeof Q.lastMessageRevision==="number"&&Number.isFinite(Q.lastMessageRevision)?Math.max(0,Math.floor(Q.lastMessageRevision)):0,V=typeof Q.lastMessageTs==="number"&&Number.isFinite(Q.lastMessageTs)?Math.max(0,Math.floor(Q.lastMessageTs)):0;$.set(X,{conversationRevision:Y,lastMessageRevision:H,lastMessageTs:V})}return $}function n0(Z){let $=I(Z.stateBornAt,0),Q=typeof Z.globalRevision==="number"&&Number.isFinite(Z.globalRevision)?Math.max(0,Math.floor(Z.globalRevision)):0,X=q6(Z.conversations);if(Q>0||$>0||X.size>0){if($>0&&$!==GZ)return{mode:"snapshot",state:s3(Z)};if(Q>=EZ)return{mode:"delta",state:{timestamp:OZ,stateBornAt:GZ,globalRevision:EZ,conversations:[],agents:Z0(Z.fallbackAgents),cronJobs:$0(Z.fallbackCronJobs)}};let K=[...r.values()].filter((B)=>!c0(B)).sort((B,O)=>O.updatedAt-B.updatedAt).map((B)=>{let O=X.get(B.id),L=O?.conversationRevision??0,D=O?.lastMessageRevision??0,U=O?.lastMessageTs??0;if(L>0||D>0){if(B.revision<=L&&B.lastMessageRevision<=D&&B.updatedAt<=U)return null}else if(U>0&&B.updatedAt<=U)return null;return D0(B,{lastMessageRevision:D,sinceTimestampMs:U>0?U:void 0})}).filter((B)=>B!==null);return{mode:"delta",state:{timestamp:OZ,stateBornAt:GZ,globalRevision:EZ,conversations:K,agents:Z0(Z.fallbackAgents),cronJobs:$0(Z.fallbackCronJobs)}}}let H=I(Z.sinceTimestampMs,0);if(!H||H<GZ)return{mode:"snapshot",state:s3(Z)};if(H>=OZ)return{mode:"delta",state:{timestamp:OZ,stateBornAt:GZ,globalRevision:EZ,conversations:[],agents:Z0(Z.fallbackAgents),cronJobs:$0(Z.fallbackCronJobs)}};let V=[...r.values()].filter((K)=>!c0(K)).filter((K)=>K.updatedAt>H).sort((K,B)=>B.updatedAt-K.updatedAt).map((K)=>{let O=X.get(K.id)?.lastMessageRevision??0;return D0(K,{sinceTimestampMs:H,lastMessageRevision:O})}),J=Z0(Z.fallbackAgents),q=$0(Z.fallbackCronJobs);return{mode:"delta",state:{timestamp:OZ,stateBornAt:GZ,globalRevision:EZ,conversations:V,agents:J,cronJobs:q}}}var n3="Assistant",s5=1500,r,jZ,_Z,YZ,GZ,OZ,EZ=0,o5,V6=2000,J6=20;var Q0=KZ(()=>{K0();r=new Map,jZ=new Map,_Z=new Map,YZ=new Map,GZ=Date.now(),OZ=Date.now(),o5=new Set});import ZZ from"node:fs";import q4 from"node:os";import IZ from"node:path";function s(Z){if(typeof Z!=="string")return null;let $=Z.trim();return $.length>0?$:null}function P6(Z){if(typeof Z==="number"&&Number.isFinite(Z))return Math.max(0,Math.floor(Z));if(typeof Z==="string"){let $=Number(Z);if(Number.isFinite($))return Math.max(0,Math.floor($))}return 0}function _0(Z){let $=Z.trim().toLowerCase();return $==="botmobile:bot:default"||$.startsWith("botmobile:bot:")}function B4(Z){if(!Z)return!0;let $=Z.trim().toLowerCase();if(!$)return!0;return $==="conversation"||$.startsWith("conversation:")}function R6(Z){let $=Array.isArray(Z.bindings)?Z.bindings:[];for(let H of $){if(!H||typeof H!=="object")continue;let V=s(H.agentId);if(!V)continue;let J=H.match,q=s(J?.channel)?.toLowerCase(),K=s(J?.accountId)?.toLowerCase();if(q!=="botmobile")continue;if(K&&K!=="default")continue;return V}let Q=Array.isArray(Z.agents?.list)?Z.agents.list:[],X=Q.find((H)=>H?.default===!0);return s(X?.id)??s(Q[0]?.id)??"assistant"}function M6(Z){let $=Z.match(L6);if(!$)return null;let Q=R($[2]);if(_0(Q))return null;return{agentId:$[1],conversationId:Q}}function e0(Z){return Z.trim().toLowerCase()}function w6(Z){return`cron:${e0(Z)}`}function L4(Z){if(!Z.toLowerCase().startsWith("cron:"))return null;let $=Z.slice(5).trim();return $.length>0?e0($):null}function S6(Z){let $=Z.match(D6);if(!$)return null;let Q=$[1].trim(),X=e0($[2]);if(!Q||!X)return null;return{agentId:Q,jobId:X}}function j6(Z){let $=s(Z);if(!$)return null;let Q=$.replace(/^cron:\s*/i,"").trim();return Q.length>0?Q:null}function C6(Z,$){let Q=s(Z.sessionFile);if(Q)return Q;let X=s(Z.sessionId);if(!X)return null;let Y=IZ.join(q4.homedir(),".openclaw","agents",$,"sessions",`${X}.jsonl`);try{if(ZZ.existsSync(Y))return Y}catch{}return null}function D4(Z){return`Task ${Z.slice(0,8).toUpperCase()}`}function a0(Z,$,Q){if(Q?.resolveAgentDisplay)return Q.resolveAgentDisplay({cfg:Z,agentId:$});let X=bZ(Z,$);return{name:X.name,emoji:X.emoji}}function U4(Z,$){if(!Z||!$?.resolveCronSnapshot)return null;return $.resolveCronSnapshot(Z)??null}function k6(Z){if(O4.test(Z))return null;let $=Z.match(U6);if(!$)return null;let Q=$[1].trim();if(!Q)return null;if(B4(Q))return null;return Q}function A6(Z){let $=Z.match(O4);if(!$)return null;let Q=R($[1]);if(_0(Q))return null;return Q}function x6(Z){if(!Z||typeof Z!=="object")return null;let $=s(Z.provider)?.toLowerCase(),Q=s(Z.surface)?.toLowerCase(),X=s(Z.chatType)?.toLowerCase(),Y=s(Z.label),H=s(Z.from);if(!($==="botmobile"||Q==="botmobile"||H!==null&&J4.test(H)))return null;if(X&&X!=="direct")return null;if(Y){let J=R(Y);if(!_0(J))return J}if(H){let J=H.match(J4);if(J&&J[1].trim().length>0){let q=R(J[1]);if(!_0(q))return q}}return null}function h6(Z,$,Q){let X=P6($.updatedAt),Y=S6(Z);if(Y){let O=C6($,Y.agentId);if(!O)return null;return{conversationId:w6(Y.jobId),agentId:Y.agentId,sessionFile:O,updatedAt:X,kind:"cron",cronJobId:Y.jobId,cronLabel:j6($.label)??void 0}}let H=s($.sessionFile);if(!H)return null;let V=M6(Z);if(V)return{conversationId:V.conversationId,agentId:V.agentId,sessionFile:H,updatedAt:X};let J=x6($.origin);if(!J)return null;let K=A6(Z)??J,B=k6(Z)??Q;return{conversationId:K,agentId:B,sessionFile:H,updatedAt:X}}function Z3(Z){let $=R6(Z),Q=IZ.join(q4.homedir(),".openclaw"),X=IZ.join(Q,"agents"),Y;try{Y=ZZ.readdirSync(X,{withFileTypes:!0}).filter((V)=>V.isDirectory()).map((V)=>V.name)}catch{return[]}let H=[];for(let V of Y){let J=IZ.join(X,V,"sessions","sessions.json"),q;try{q=JSON.parse(ZZ.readFileSync(J,"utf8"))}catch{continue}for(let[K,B]of Object.entries(q)){let O=h6(K,B,$);if(!O)continue;H.push(O)}}return H.sort((V,J)=>J.updatedAt-V.updatedAt),H}function T6(Z,$,Q){let X=[],Y=0;if(Q){let H=Z.indexOf(10);if(H===-1)return[];Y=H+1}for(let H=Y;H<Z.length;H++){if(Z[H]!==10)continue;let V=Z.subarray(Y,H),J=$+Y;if(Y=H+1,V.length===0)continue;let q=V.toString("utf8").trim();if(!q)continue;X.push({line:q,offset:J})}if(Y<Z.length){let V=Z.subarray(Y).toString("utf8").trim();if(V)X.push({line:V,offset:$+Y})}return X}function F4(Z){if(!Array.isArray(Z))return"";let $=[];for(let Q of Z)if(Q&&typeof Q==="object"&&Q.type==="text"&&typeof Q.text==="string")$.push(Q.text);return $.join(`
3
- `)}function _4(Z){try{return JSON.parse(Z)}catch{return null}}function G4(Z,$){if(typeof Z==="number"&&Number.isFinite(Z)&&Z>0)return Math.floor(Z);if(typeof Z==="string"&&Z.trim().length>0){let Q=Number(Z);if(Number.isFinite(Q)&&Q>0)return Math.floor(Q);let X=Date.parse(Z);if(Number.isFinite(X)&&X>0)return Math.floor(X)}if(typeof $==="number"&&Number.isFinite($)&&$>0)return Math.floor($);if(typeof $==="string"&&$.trim().length>0){let Q=Number($);if(Number.isFinite(Q)&&Q>0)return Math.floor(Q);let X=Date.parse($);if(Number.isFinite(X)&&X>0)return Math.floor(X)}return 0}function W4(Z){if(!N6.test(Z))return!1;let $=Z.match(E6);if(!$)return!1;let Q=$[1];return Q==="user"||Q==="assistant"}function b6(Z){let $=Z.trim();if(!G6.test($))return $;let Q=Array.from($.matchAll(_6));if(Q.length===0)return $;let X=Q[Q.length-1],Y=typeof X.index==="number"?X.index:0;return $.slice(Y).trim()}function z4(Z){let $=Z.match(z6),Q=$?$[1].trim():void 0,X=Z.replace(W6,"").trim();return{clean:b6(X).replace(F6,"").trim(),messageId:Q}}function f6(Z){let{sessionFile:$,limit:Q}=Z,X=R(Z.conversationId),Y=IZ.basename($),H=null;try{H=ZZ.openSync($,"r");let V=ZZ.fstatSync(H).size;if(V<=0)return[];let J=Math.min(K4,V);while(!0){let q=Math.max(0,V-J),K=V-q,B=Buffer.allocUnsafe(K);ZZ.readSync(H,B,0,K,q);let O=T6(B,q,q>0),L=[];for(let U=O.length-1;U>=0&&L.length<Q;U--){let z=O[U];if(!W4(z.line))continue;let N=_4(z.line);if(!N||N.type!=="message"||!N.message)continue;let G=N.message;if(G.role!=="user"&&G.role!=="assistant")continue;let T=F4(G.content);if(!T.trim())continue;let A=G.role==="user"?"user":"bot",p=G4(G.timestamp,N.timestamp),b,S;if(A==="user"){let{clean:c,messageId:j}=z4(T);b=c,S=j?`u:${j}`:`t:${Y}:${z.offset}`}else b=T,S=`t:${Y}:${z.offset}`;if(!b.trim())continue;L.push({id:S,conversationId:X,role:A,content:b,timestamp:p,isStreaming:!1})}let D=L.reverse();if(D.length>=Q||q===0)return D;if(J>=V4)return D;J=Math.min(V,J*2,V4)}}catch{return[]}finally{if(H!==null)try{ZZ.closeSync(H)}catch{}}}function N4(Z,$,Q,X,Y){let H=IZ.basename(Z),V=R($.conversationId),J,q;try{J=ZZ.openSync(Z,"r"),q=ZZ.fstatSync(J).size}catch{return{messages:[],cursor:X}}try{if(q<X.offset)X={offset:Math.max(0,q-K4)};if(q<=X.offset)return{messages:[],cursor:X};let K=X.offset,B=q-K,O=Buffer.alloc(B);ZZ.readSync(J,O,0,B,K);let L=0;if(K>0){let j=Buffer.alloc(1);try{if(ZZ.readSync(J,j,0,1,K-1),j[0]!==10){let E=O.indexOf(10);if(E===-1)return{messages:[],cursor:{offset:K}};L=E+1}}catch{}}let D=O.subarray(L),U=K+L,z=D.toString("utf8");if(!z)return{messages:[],cursor:{offset:q}};let N=z.endsWith(`
4
- `),G=z.split(`
5
- `);if(N)G.pop();else G.pop();let T=$.cronJobId??L4(V),A=U4(T,Y),p=$.kind==="cron"?{id:$.cronAgentId??$.agentId,name:$.cronLabel??A?.name??(T?D4(T):"Scheduled Task"),emoji:$.cronAgentEmoji??A?.agentEmoji??"\uD83D\uDD52"}:(()=>{let j=a0(Q,$.agentId,Y);return{id:$.agentId,name:j.name??$.agentId,emoji:j.emoji}})(),b=[],S=U;for(let j of G){let E=Buffer.byteLength(j,"utf8")+1;if(j.trim()){if(!W4(j)){S+=E;continue}let v=_4(j);if(v&&v.type==="message"&&v.message){let W=v.message;if(W.role==="user"||W.role==="assistant"){let m=F4(W.content);if(m.trim()){let x=W.role==="user"?"user":"bot",l=G4(W.timestamp,v.timestamp),n,QZ;if(x==="user"){let{clean:d,messageId:hZ}=z4(m);n=d,QZ=hZ?`u:${hZ}`:`t:${H}:${S}`}else n=m,QZ=`t:${H}:${S}`;if(n.trim())b.push({conversationId:V,agentId:$.agentId,agent:p,role:x,content:n,timestamp:l,stableId:QZ})}}}}S+=E}return{messages:b,cursor:{offset:N?q:S}}}finally{try{ZZ.closeSync(J)}catch{}}}function E4(Z,$){let Q=Z3(Z),X=new Map;for(let V of Q){let J=X.get(V.conversationId)??[];J.push(V),X.set(V.conversationId,J)}let Y=[...X.entries()].map(([V,J])=>{let q=[...J].sort((O,L)=>L.updatedAt-O.updatedAt),K=[],B=new Set;for(let O of q){if(B.has(O.sessionFile))continue;B.add(O.sessionFile),K.push(O)}return{conversationId:V,mappings:K,updatedAt:K[0]?.updatedAt??0}}).sort((V,J)=>J.updatedAt-V.updatedAt),H=[];for(let V=0;V<Y.length;V++){let J=Y[V],q=V<O6,K=J.mappings.slice(0,B6),B=new Map;if(q)for(let W of K){let m=f6({sessionFile:W.sessionFile,conversationId:J.conversationId,limit:t0});for(let x of m){let l=B.get(x.id);if(!l||x.timestamp>=l.timestamp)B.set(x.id,x)}}let O=[...B.values()].sort((W,m)=>{if(W.timestamp===m.timestamp)return W.id.localeCompare(m.id);return W.timestamp-m.timestamp}),L=O.length>t0?O.slice(O.length-t0):O,D=L.map((W)=>W.timestamp).filter((W)=>W>0),U=J.mappings.map((W)=>W.updatedAt).filter((W)=>W>0),z=U.length>0?Math.min(...U):J.updatedAt,N=U.length>0?Math.max(...U):J.updatedAt,G=D.length>0?Math.min(...D):z,T=D.length>0?Math.max(N,...D):N,A=J.mappings.find((W)=>!B4(W.agentId))??J.mappings[0],p=A.cronJobId??L4(J.conversationId),b=U4(p,$),S=J.conversationId.toLowerCase().startsWith("cron:"),c=S?A.cronAgentId??b?.agentId??A.agentId:void 0,j=c?a0(Z,c,$):void 0,E=S?A.cronLabel??b?.name??(p?D4(p):"Scheduled Task"):void 0,v=S?{id:c??A.agentId,name:E??"Scheduled Task",emoji:A.cronAgentEmoji??b?.agentEmoji??"\uD83D\uDD52"}:(()=>{let W=a0(Z,A.agentId,$);return{id:A.agentId,name:W.name??A.agentId,emoji:W.emoji}})();H.push({id:J.conversationId,agent:v,createdAt:G,updatedAt:T,kind:S?"cron":void 0,cronJobId:S?p??void 0:void 0,cronName:S?E:void 0,cronAgentId:S?c:void 0,cronAgentName:S?b?.agentName??j?.name:void 0,cronAgentEmoji:S?A.cronAgentEmoji??b?.agentEmoji??j?.emoji:void 0,messages:L})}return console.log(`${K6} loaded ${H.length} conversations (${H.reduce((V,J)=>V+J.messages.length,0)} messages) [tail-read]`),H}var K6="[session-loader]",t0=100,O6=50,B6=3,K4=8388608,V4=134217728,L6,D6,U6,O4,J4,F6,_6,G6,W6,z6,N6,E6;var P4=KZ(()=>{q0();K0();L6=/^agent:([^:]+):botmobil[e]?:direct:(.+)$/i,D6=/^agent:([^:]+):cron:([^:]+)(?::run:([^:]+))?$/i,U6=/^agent:([^:]+):/i,O4=/^agent:conversation:([^:]+):main$/i,J4=/^botmobile:user:(.+)$/i,F6=/^\[(?:BotMobile|Botmobil[e]?) user:\S+ [^\]]+\]\s*/i,_6=/\[(?:BotMobile|Botmobil[e]?) user:\S+ [^\]]+\]\s*/gi,G6=/^\[Queued messages while agent was busy\]/i,W6=/\n\[message_id: [^\]]+\]\s*$/i,z6=/\[message_id:\s*([^\]]+)\]\s*$/i,N6=/"type"\s*:\s*"message"/,E6=/"role"\s*:\s*"([^"]+)"/});import{createRequire as I6}from"node:module";function X0(Z){return y6[Z]??`0x${Z.toString(16)}`}function v6(){let Z=u6.version;if(typeof Z==="string"){let $=Z.trim();if($.length>0)return $}return"dev"}function w4(Z){if($3)return Buffer.from($3(Z));return Buffer.from(JSON.stringify(Z),"utf8")}function S4(Z){let $;if(Q3)$=Q3(Z);else{let V=Buffer.from(Z).toString("utf8");$=JSON.parse(V)}if(!$||typeof $!=="object")throw Error("Invalid wire envelope payload");let Q=$,X=typeof Q.type==="bigint"?Number(Q.type):Q.type,Y=typeof Q.seq==="bigint"?Number(Q.seq):Q.seq,H=typeof Q.ts==="bigint"?Number(Q.ts):Q.ts;if(typeof X!=="number")throw Error("Invalid wire envelope type");if(typeof Y!=="number")throw Error("Invalid wire envelope seq");if(typeof H!=="number")throw Error("Invalid wire envelope ts");return{type:X,seq:Y,ts:H,payload:Q.payload}}function RZ(Z){if(typeof Z==="number"&&Number.isFinite(Z))return Z;if(typeof Z==="bigint")return Number(Z);return null}function yZ(Z){if(typeof Z!=="string")return null;let $=Z.trim();return $.length>0?$:null}function m6(Z){if(!Array.isArray(Z))return;let $=[];for(let Q of Z){if(!Q||typeof Q!=="object")continue;let X=Q,Y=yZ(X.id);if(!Y)continue;let H=RZ(X.conversationRevision),V=RZ(X.lastMessageRevision),J=RZ(X.lastMessageTs);$.push({id:Y,conversationRevision:H!==null?Math.max(0,Math.floor(H)):void 0,lastMessageRevision:V!==null?Math.max(0,Math.floor(V)):void 0,lastMessageTs:J!==null?Math.max(0,Math.floor(J)):void 0})}return $.length>0?$:void 0}function g6(Z){if(!Array.isArray(Z))return[];let $=[];for(let Q of Z){if(!Q||typeof Q!=="object")continue;let X=Q,Y=yZ(X.transferId),H=yZ(X.fileName);if(!Y||!H)continue;$.push({transferId:Y,fileName:H,mimeType:yZ(X.mimeType)??"application/octet-stream",size:typeof X.size==="number"?X.size:0})}return $}function j4(Z){if(Z.type===F.stateSyncRequest){let X=Z.payload??{},Y=RZ(X.stateBornAt),H=RZ(X.globalRevision),V=m6(X.conversations),J=[],q=RZ(X.lastAgentTs);if(q!==null&&q>0)J.push(q);let K=RZ(X.lastCronTs);if(K!==null&&K>0)J.push(K);if(V){for(let O of V)if(typeof O.lastMessageTs==="number"&&Number.isFinite(O.lastMessageTs)&&O.lastMessageTs>0)J.push(O.lastMessageTs)}return{kind:"legacy",envelope:{type:"state_sync_request",sinceTimestampMs:J.length>0?Math.min(...J):void 0,stateBornAt:Y!==null&&Y>0?Math.max(0,Math.floor(Y)):void 0,globalRevision:H!==null&&H>=0?Math.max(0,Math.floor(H)):void 0,conversations:V}}}if(Z.type!==F.command)return{kind:"ignore",reason:`unsupported_type_${Z.type}`};let $=Z.payload??{};if(typeof $.id!=="string"||$.id.length===0||typeof $.action!=="string")return{kind:"ignore",reason:"invalid_command_payload"};let Q=$.data??{};switch($.action){case"send_message":{let X=typeof Q.conversationId==="string"?Q.conversationId:"",Y=typeof Q.content==="string"?Q.content:"",H=typeof Q.agentId==="string"&&Q.agentId.length>0?Q.agentId:void 0,V=typeof Q.messageId==="string"&&Q.messageId.length>0?Q.messageId:typeof Q.clientMessageId==="string"&&Q.clientMessageId.length>0?Q.clientMessageId:void 0;if(!X||!Y&&!Array.isArray(Q.attachments))return{kind:"ignore",reason:"invalid_send_message"};let J=g6(Q.attachments);return{kind:"command",commandId:$.id,envelope:{type:"message",id:V??crypto.randomUUID(),conversationId:X,from:"user",body:Y,timestamp:Date.now(),agentId:H,pendingAttachments:J.length>0?J:void 0}}}case"stop_generation":{let X=typeof Q.conversationId==="string"?Q.conversationId:"";if(!X)return{kind:"ignore",reason:"invalid_stop_generation"};return{kind:"command",commandId:$.id,envelope:{type:"stop_generation",conversationId:X}}}case"cron_run":{let X=typeof Q.cronJobId==="string"?Q.cronJobId:"";if(!X)return{kind:"ignore",reason:"invalid_cron_run"};return{kind:"command",commandId:$.id,envelope:{type:"cron_run",jobId:X}}}case"cron_toggle":{let X=typeof Q.cronJobId==="string"?Q.cronJobId:"",Y=Q.enabled===!0;if(!X)return{kind:"ignore",reason:"invalid_cron_toggle"};return{kind:"command",commandId:$.id,envelope:{type:"cron_toggle",jobId:X,enabled:Y}}}case"cron_create_from_prompt":{let X=typeof Q.agentId==="string"?Q.agentId.trim():"",Y=typeof Q.description==="string"?Q.description.trim():"",H=typeof Q.name==="string"?Q.name.trim():"",V=RZ(Q.everyMs),J=V!==null&&V>=60000&&V<=2592000000?Math.floor(V):void 0;if(!X||!Y)return{kind:"ignore",reason:"invalid_cron_create_from_prompt"};return{kind:"command",commandId:$.id,envelope:{type:"cron_create_from_prompt",agentId:X,description:Y,name:H.length>0?H:void 0,everyMs:J}}}case"client_state":{let X=Q.isForeground===!0,Y=yZ(Q.activeTab),H=Y==="screen"||Y==="agents"||Y==="tasks"||Y==="settings"?Y:void 0,V=yZ(Q.activeConversationId)??void 0;return{kind:"command",commandId:$.id,envelope:{type:"client_state",isForeground:X,activeTab:H,activeConversationId:V,updatedAt:Date.now()}}}case"new_conversation":case"full_sync":return{kind:"command",commandId:$.id,envelope:{type:"state_sync_request",sinceTimestampMs:void 0}};default:return{kind:"ignore",reason:`unknown_action_${$.action}`}}}var F,y6,R4,u6,M4,$3=null,Q3=null;var C4=KZ(()=>{Q0();F={stateSyncRequest:1,snapshotAgents:2,snapshotCron:3,snapshotConversations:4,conversationDelta:5,streamBatch:6,streamEnd:7,command:16,commandAck:17,agentStatus:18,heartbeat:32,syncBegin:48,syncEnd:49,fileChunk:64,fileChunkAck:65,fileComplete:66,error:255},y6=Object.fromEntries(Object.entries(F).map(([Z,$])=>[$,Z]));R4=I6(import.meta.url),u6=(()=>{try{return R4("../package.json")}catch{return{}}})();M4=v6();try{let Z=R4("msgpackr"),$=new Z.Packr({useRecords:!1});$3=(Q)=>$.pack(Q),Q3=(Q)=>Z.unpack(Q)}catch{}});import k4 from"node:fs";import X3 from"node:path";import p6 from"node:os";class Y3{transfers=new Map;completed=new Map;sendWire;constructor(Z){this.sendWire=Z}handleChunk(Z){let $=this.parseChunkPayload(Z);if(!$)return;let Q=this.transfers.get($.transferId);if(!Q)Q=this.createTransfer($),this.transfers.set($.transferId,Q),console.log(`${Y0} new transfer ${$.transferId} file=${$.fileName} size=${$.totalSize} chunks=${$.totalChunks}`);Q.lastActivityAt=Date.now(),this.resetTimer($.transferId,Q);let X=Buffer.isBuffer($.data)?$.data:Buffer.from($.data);if(Q.receivedChunks.set($.chunkIndex,X),this.sendWire(c6,{transferId:$.transferId,chunkIndex:$.chunkIndex}),Q.receivedChunks.size>=Q.totalChunks)this.finalizeTransfer($.transferId,Q)}getFilePath(Z){return this.completed.get(Z)?.filePath}getCompletedTransfer(Z){return this.completed.get(Z)}dispose(){for(let[,Z]of this.transfers)clearTimeout(Z.timer);this.transfers.clear()}parseChunkPayload(Z){if(!Z||typeof Z!=="object")return null;let $=Z,Q=typeof $.transferId==="string"?$.transferId.trim():"",X=typeof $.fileName==="string"?$.fileName.trim():"",Y=typeof $.mimeType==="string"?$.mimeType.trim():"application/octet-stream",H=typeof $.totalSize==="number"?$.totalSize:0,V=typeof $.chunkIndex==="number"?$.chunkIndex:typeof $.chunkIndex==="bigint"?Number($.chunkIndex):-1,J=typeof $.totalChunks==="number"?$.totalChunks:typeof $.totalChunks==="bigint"?Number($.totalChunks):0,q=$.data;if(!Q||!X||J<=0||V<0)return null;if(!Buffer.isBuffer(q)&&!(q instanceof Uint8Array))return null;return{transferId:Q,fileName:X,mimeType:Y,totalSize:H,chunkIndex:V,totalChunks:J,data:q}}createTransfer(Z){let $=setTimeout(()=>{this.timeoutTransfer(Z.transferId)},A4);return{fileName:Z.fileName,mimeType:Z.mimeType,totalSize:Z.totalSize,totalChunks:Z.totalChunks,receivedChunks:new Map,lastActivityAt:Date.now(),timer:$}}resetTimer(Z,$){clearTimeout($.timer),$.timer=setTimeout(()=>{this.timeoutTransfer(Z)},A4)}timeoutTransfer(Z){let $=this.transfers.get(Z);if(!$)return;console.warn(`${Y0} transfer ${Z} timed out (received ${$.receivedChunks.size}/${$.totalChunks} chunks)`),clearTimeout($.timer),this.transfers.delete(Z),this.sendWire(G0,{transferId:Z,success:!1,error:"Transfer timed out"})}finalizeTransfer(Z,$){clearTimeout($.timer),this.transfers.delete(Z);let Q=[];for(let V=0;V<$.totalChunks;V++){let J=$.receivedChunks.get(V);if(!J){console.error(`${Y0} transfer ${Z} missing chunk ${V}`),this.sendWire(G0,{transferId:Z,success:!1,error:`Missing chunk ${V}`});return}Q.push(J)}let X=Buffer.concat(Q),Y=X3.basename($.fileName).replace(/[^\w.\-]/g,"_")||"file",H=X3.join(x4,`${Z}-${Y}`);try{k4.mkdirSync(x4,{recursive:!0}),k4.writeFileSync(H,X)}catch(V){console.error(`${Y0} transfer ${Z} write failed: ${String(V)}`),this.sendWire(G0,{transferId:Z,success:!1,error:`Write failed: ${String(V)}`});return}this.completed.set(Z,{fileName:$.fileName,mimeType:$.mimeType,filePath:H,size:X.length}),console.log(`${Y0} transfer ${Z} complete: ${H} (${X.length} bytes)`),this.sendWire(G0,{transferId:Z,success:!0})}}var Y0="[botmobile:file-receiver]",A4=60000,x4,c6=65,G0=66;var h4=KZ(()=>{x4=X3.join(p6.homedir(),".openclaw","uploads")});import uZ from"ws";function X7(Z){return new Promise(($)=>setTimeout($,Z))}async function Y7(){if(!W0)W0=import("node-datachannel");let Z;try{Z=await W0}catch($){W0=null;let Q=String($??"");if(Q.includes("node_datachannel.node")||Q.includes("Cannot find module '../../../build/Release/node_datachannel.node'"))throw Error("node-datachannel native binary is missing. Reinstall the plugin with npm scripts enabled (NPM_CONFIG_IGNORE_SCRIPTS=false).");throw $}if(!I4){I4=!0;try{Z.initLogger?.("Error")}catch{}}return Z}function w(Z){if(typeof Z!=="string")return null;let $=Z.trim();return $.length>0?$:null}function H7(Z){if(typeof Z==="string"){let X=Z.trim();if(!X)return null;return{candidate:X}}if(!Z||typeof Z!=="object")return null;let $=Z,Q=w($.candidate);if(!Q)return null;return{candidate:Q,sdpMid:w($.sdpMid)??void 0}}function V7(Z){if(!Z||typeof Z!=="object")return["stun:stun.cloudflare.com:3478"];let Q=Z,X=Array.isArray(Q.urls)?Q.urls.filter((J)=>typeof J==="string"&&J.trim().length>0):typeof Q.urls==="string"?Q.urls.split(",").map((J)=>J.trim()).filter((J)=>J.length>0):[],Y=w(Q.username),H=w(Q.credential);if(X.length===0||!Y||!H)return["stun:stun.cloudflare.com:3478"];let V=["stun:stun.cloudflare.com:3478"];for(let J of X){let q=J7(J);if(!q)continue;V.push({hostname:q.hostname,port:q.port,username:Y,password:H,relayType:q.relayType})}return V}function J7(Z){let $=Z.match(/^(turns?):([^:?]+):(\d+)/);if(!$)return null;let Q=$[1],X=$[2],Y=parseInt($[3],10),V=Z.match(/[?&]transport=(udp|tcp)/i)?.[1]?.toLowerCase()??"udp",J;if(Q==="turns")J="TurnTls";else if(V==="tcp")J="TurnTcp";else J="TurnUdp";return{hostname:X,port:Y,relayType:J}}function q7(Z){return{id:Z.id,conversationId:Z.conversationId,role:Z.from==="user"?"user":"bot",content:Z.body,timestamp:Z.timestamp,isStreaming:!1}}function K7(Z){if(!Z)return;return{...Z,skills:Z.skills?[...Z.skills]:void 0,skillDetails:Z.skillDetails?Z.skillDetails.map(($)=>({...$})):void 0,toolsAllow:Z.toolsAllow?[...Z.toolsAllow]:void 0,toolsDeny:Z.toolsDeny?[...Z.toolsDeny]:void 0}}function O7(Z){let $=Z.status==="working";return{id:Z.agentId,name:Z.name,emoji:Z.emoji,color:Z.color,details:K7(Z.details),queue:$?1:0,lastUpdated:Z.lastActivityAt??Date.now(),usage:{mode:"tokens",value:Math.max(0,(Z.sessionTokensIn??0)+(Z.sessionTokensOut??0))},isRunning:$,currentTask:Z.activeTool}}function B7(Z){return{id:Z.id,name:Z.name,enabled:Z.enabled,isRunning:Z.isRunning===!0,lastUpdated:Date.now(),agentId:Z.agentId,agentName:Z.agentName,agentEmoji:Z.agentEmoji,nextRunAt:Z.nextRunAt,lastRunAt:Z.lastRunAt,lastRunStatus:Z.lastRunStatus,lastRunSummary:Z.lastRunSummary}}function L7(Z){switch(Z.type){case"message":return[{type:F.conversationDelta,payload:{id:Z.conversationId,updatedAt:Z.timestamp,messages:[q7(Z)]}}];case"conversation_list":{let $=Date.now();return[{type:F.snapshotConversations,payload:{timestamp:$,conversations:Z.conversations.map((Q)=>{let X=o0(Q.id);return{id:Q.id,name:Q.name,agent:X?.agent,createdAt:Q.createdAt??X?.createdAt??$,updatedAt:Q.lastActivity??X?.updatedAt??$,revision:X?.revision,lastMessageRevision:X?.lastMessageRevision,activity:X?.activity}})}}]}case"agent_list":return[{type:F.snapshotAgents,payload:{timestamp:Date.now(),agents:Z.agents.map(O7)}}];case"agent_status":return[{type:F.agentStatus,payload:{id:Z.agentId,activeConversationId:Z.activeConversationId,isRunning:Z.status==="working",queue:Z.status==="working"?1:0,color:Z.color,details:Z.details,currentTask:Z.activeTool,lastUpdated:Z.lastActivityAt??Date.now(),usage:{mode:"tokens",value:Math.max(0,(Z.sessionTokensIn??0)+(Z.sessionTokensOut??0))},errorMessage:Z.errorMessage}}];case"cron_list":return[{type:F.snapshotCron,payload:{timestamp:Date.now(),cronJobs:Z.jobs.map(B7)}}];case"state_snapshot":case"state_delta":{let $=[],Q=crypto.randomUUID().slice(0,8),X=Z.state.conversations.length;$.push({type:F.syncBegin,payload:{syncId:Q,totalConversations:X,pluginVersion:M4,stateBornAt:Z.state.stateBornAt,globalRevision:Z.state.globalRevision}}),$.push({type:F.snapshotAgents,payload:{timestamp:Z.state.timestamp,stateBornAt:Z.state.stateBornAt,globalRevision:Z.state.globalRevision,agents:Z.state.agents}}),$.push({type:F.snapshotCron,payload:{timestamp:Z.state.timestamp,stateBornAt:Z.state.stateBornAt,globalRevision:Z.state.globalRevision,cronJobs:Z.state.cronJobs}}),$.push({type:F.snapshotConversations,payload:{timestamp:Z.state.timestamp,stateBornAt:Z.state.stateBornAt,globalRevision:Z.state.globalRevision,conversations:Z.state.conversations.map((Y)=>({id:Y.id,kind:Y.kind,cronJobId:Y.cronJobId,cronName:Y.cronName,cronAgentId:Y.cronAgentId,cronAgentName:Y.cronAgentName,cronAgentEmoji:Y.cronAgentEmoji,agent:Y.agent,createdAt:Y.createdAt,updatedAt:Y.updatedAt,revision:Y.revision,lastMessageRevision:Y.lastMessageRevision,activity:Y.activity}))}});for(let Y of Z.state.conversations)$.push({type:F.conversationDelta,payload:{id:Y.id,kind:Y.kind,cronJobId:Y.cronJobId,cronName:Y.cronName,cronAgentId:Y.cronAgentId,cronAgentName:Y.cronAgentName,cronAgentEmoji:Y.cronAgentEmoji,agent:Y.agent,createdAt:Y.createdAt,updatedAt:Y.updatedAt,revision:Y.revision,lastMessageRevision:Y.lastMessageRevision,activity:Y.activity,messages:Y.messages}});return $.push({type:F.syncEnd,payload:{syncId:Q,sentConversations:X,stateBornAt:Z.state.stateBornAt,globalRevision:Z.state.globalRevision}}),$}case"gateway_heartbeat":return[{type:F.heartbeat,payload:{kind:"gateway",timestamp:Z.timestamp,uptimeMs:Z.uptimeMs}}];case"error":return[{type:F.error,payload:{code:Z.code,message:Z.message,conversationId:Z.conversationId}}];case"ping":case"pong":default:return[]}}function y4(Z,$){if(Z===F.heartbeat)return"";if(!$||typeof $!=="object")return String($??"");let Q=$;switch(Z){case F.conversationDelta:{let X=Array.isArray(Q.messages)?Q.messages.length:0;return`conv=${w(Q.id)??"?"} msgs=${X}`}case F.snapshotAgents:return`agents=${Array.isArray(Q.agents)?Q.agents.length:0}`;case F.snapshotCron:return`jobs=${Array.isArray(Q.cronJobs)?Q.cronJobs.length:0}`;case F.snapshotConversations:return`conversations=${Array.isArray(Q.conversations)?Q.conversations.length:0}`;case F.streamBatch:return`conv=${w(Q.conversationId)??"?"} msg=${w(Q.messageId)?.slice(0,8)??"?"} +${(w(Q.tokens)??"").length}ch`;case F.streamEnd:return`conv=${w(Q.conversationId)??"?"} msg=${w(Q.messageId)?.slice(0,8)??"?"} len=${(w(Q.finalContent)??"").length}`;case F.command:return`action=${w(Q.action)??"?"} id=${w(Q.id)??"?"}`;case F.commandAck:return`id=${w(Q.commandId)??"?"} ok=${Q.ok}`;case F.agentStatus:return`agent=${w(Q.id)??"?"} running=${Q.isRunning}`;case F.syncBegin:return`syncId=${w(Q.syncId)??"?"} total=${Q.totalConversations}`;case F.syncEnd:return`syncId=${w(Q.syncId)??"?"} sent=${Q.sentConversations}`;case F.error:return`code=${w(Q.code)??"?"} msg=${w(Q.message)??"?"}`;case F.stateSyncRequest:return`globalRevision=${Q.globalRevision??"nil"} stateBornAt=${Q.stateBornAt??"nil"}`;default:return JSON.stringify($).slice(0,120)}}class H3{account;onLegacyEnvelope;onSignalingStatus;onDataChannelStatus;signalingWs=null;peerConnection=null;dataChannel=null;currentSessionId=null;currentOfferRequestId=null;outboundSeq=1;outboundQueue=[];outboundQueueBytes=0;streamTextByMessageId=new Map;pendingStreamBatches=new Map;dataChannelDisconnectedAt=null;awaitingStateSyncRequest=!1;heartbeatInterval=null;lastHeartbeatReceivedAt=0;lastHeartbeatRttMs=null;lastPushSentAt=0;clientIsForeground=null;clientStateUpdatedAt=0;pendingPushTimer=null;pendingPushRequest=null;resyncRequired=!1;pendingRemoteCandidates=[];remoteDescriptionApplied=!1;pendingSignalQueue=[];signalingHeartbeatInterval=null;lastSignalingPongAt=0;stopped=!1;answerGatherTimer=null;_fileReceiver=null;lastSnapshotSignatureByType=new Map;lastSnapshotSentAtByType=new Map;constructor(Z){this.account=Z.account,this.onLegacyEnvelope=Z.onLegacyEnvelope,this.onSignalingStatus=Z.onSignalingStatus,this.onDataChannelStatus=Z.onDataChannelStatus}get fileReceiver(){return this._fileReceiver}async run(Z){let $=T4;while(!Z.aborted&&!this.stopped){try{await this.connectSignalingOnce(Z),$=T4}catch(Q){console.error(`${_} signaling loop error: ${String(Q)}`)}if(Z.aborted||this.stopped)break;await X7($),$=Math.min($*2,l6)}this.cleanup()}stop(){this.stopped=!0,this.cleanup()}sendLegacyEnvelope(Z){if(Z.type==="stream_start"){this.handleLegacyStreamStart(Z);return}if(Z.type==="stream_token"){this.handleLegacyStreamToken(Z);return}if(Z.type==="stream_end"){this.handleLegacyStreamEnd(Z);return}let $=L7(Z);for(let Q of $)this.sendWire(Q.type,Q.payload)}async connectSignalingOnce(Z){let $=`${this.account.workerUrl.replace(/^http/,"ws")}/ws/signal`;await new Promise((Q,X)=>{let Y=!1,H=null,V=new uZ($,{headers:{authorization:`BotMobileSecret ${this.account.sharedSecret}`}});this.signalingWs=V;let J=(q)=>{if(Y)return;if(Y=!0,H)Z.removeEventListener("abort",H),H=null;q()};H=()=>{this.stopSignalingHeartbeat();try{V.close()}catch{}J(()=>Q())},Z.addEventListener("abort",H,{once:!0}),V.on("open",()=>{this.onSignalingStatus?.(!0),this.startSignalingHeartbeat(),this.flushPendingSignalQueue()}),V.on("message",(q)=>{let K=q.toString(),B;try{B=JSON.parse(K)}catch{console.warn(`${_} invalid signaling message`);return}this.handleSignalingMessage(B).catch((O)=>{console.error(`${_} signaling message handler failed: ${String(O)}`)})}),V.on("close",()=>{this.stopSignalingHeartbeat(),this.onSignalingStatus?.(!1),this.signalingWs=null,J(()=>Q())}),V.on("error",(q)=>{this.stopSignalingHeartbeat(),this.onSignalingStatus?.(!1),this.signalingWs=null,J(()=>X(q))})})}async handleSignalingMessage(Z){if(!Z||typeof Z!=="object")return;let $=Z;if($.type==="pong"){this.lastSignalingPongAt=Date.now();return}if($.type==="ping"){this.sendSignal({type:"pong",ts:Date.now()});return}if($.type==="offer"){await this.handleOffer(Z);return}if($.type==="ice"){this.handleRemoteIce(Z);return}if($.type==="error")console.warn(`${_} signaling error: ${JSON.stringify(Z)}`)}sendSignalingPing(){let Z=this.signalingWs;if(!Z||Z.readyState!==uZ.OPEN)return;try{Z.send(JSON.stringify({type:"ping",ts:Date.now()}))}catch($){console.warn(`${_} signaling ping send failed: ${String($)}`);try{Z.close()}catch{}}}startSignalingHeartbeat(){this.stopSignalingHeartbeat(),this.lastSignalingPongAt=Date.now(),this.sendSignalingPing(),this.signalingHeartbeatInterval=setInterval(()=>{let Z=this.signalingWs;if(!Z||Z.readyState!==uZ.OPEN)return;if(Date.now()-this.lastSignalingPongAt>a6){console.warn(`${_} signaling heartbeat stale; forcing reconnect`);try{Z.close()}catch{}return}this.sendSignalingPing()},t6)}stopSignalingHeartbeat(){if(this.signalingHeartbeatInterval)clearInterval(this.signalingHeartbeatInterval),this.signalingHeartbeatInterval=null;this.lastSignalingPongAt=0}async handleOffer(Z){let $=w(Z.requestId),Q=w(Z.sdp);if(!$||!Q){this.sendSignal({type:"error",requestId:Z.requestId,code:"INVALID_OFFER",message:"Offer payload is missing requestId or sdp"},{queueIfClosed:!0});return}if(this.answerGatherTimer)clearTimeout(this.answerGatherTimer),this.answerGatherTimer=null;if(this.peerConnection||this.dataChannel)console.log(`${_} closing stale peer connection before new offer`),this.closePeerConnection();this.currentOfferRequestId=$,this.currentSessionId=Z.sessionId??crypto.randomUUID().replace(/-/g,""),this.pendingRemoteCandidates=[],this.remoteDescriptionApplied=!1,this.awaitingStateSyncRequest=!0;let X;try{X=await this.ensurePeerConnection(Z.turnCredentials)}catch(Y){console.error(`${_} peer connection creation failed requestId=${$} error=${String(Y)}`),this.sendSignal({type:"error",requestId:$,code:"PEER_CREATE_FAILED",message:String(Y)},{queueIfClosed:!0});return}try{console.log(`${_} setRemoteDescription offer sdp_len=${Q.length} ice_candidates=${Array.isArray(Z.iceCandidates)?Z.iceCandidates.length:0}`);let H=(Q.split(`\r
6
- `).length>1?Q.split(`\r
7
- `):Q.split(`
8
- `)).filter((V)=>V.startsWith("a=ice-")||V.startsWith("a=fingerprint")||V.startsWith("a=setup")||V.startsWith("m="));if(console.log(`${_} SDP ice-relevant lines: ${H.join(" | ")}`),X.setRemoteDescription?.(Q,"offer"),this.remoteDescriptionApplied=!0,console.log(`${_} setRemoteDescription success`),Array.isArray(Z.iceCandidates))for(let V of Z.iceCandidates)this.enqueuePendingRemoteCandidate(V,this.currentSessionId??void 0);this.flushPendingRemoteCandidates(),X.setLocalDescription?.(),console.log(`${_} setLocalDescription (answer) triggered`)}catch(Y){console.error(`${_} offer processing failed: ${String(Y)}`),this.sendSignal({type:"error",requestId:$,code:"OFFER_PROCESS_FAILED",message:String(Y)},{queueIfClosed:!0})}}async ensurePeerConnection(Z){if(this.peerConnection)return this.peerConnection;let $=await Y7(),Q={iceServers:V7(Z)},X=new $.PeerConnection(`botmobile-${Date.now()}`,Q);this.peerConnection=X,this.dataChannelDisconnectedAt=Date.now(),this.awaitingStateSyncRequest=!0;let Y=[],H=null,V=this.currentOfferRequestId,J=this.currentSessionId,q=()=>{if(this.answerGatherTimer)clearTimeout(this.answerGatherTimer),this.answerGatherTimer=null;if(this.peerConnection!==X)return;if(!H)return;let K=H;H=null,console.log(`${_} sending answer with ${Y.length} bundled candidates`),this.sendSignal({type:"answer",requestId:V,sessionId:J,sdp:K,iceCandidates:Y.slice()},{queueIfClosed:!0})};return X.onLocalDescription?.((K,B)=>{if(this.peerConnection!==X)return;if(console.log(`${_} onLocalDescription type=${B} sdp_len=${K?.length??0} requestId=${V} wsOpen=${this.signalingWs?.readyState===uZ.OPEN}`),B!=="answer")return;H=K,this.answerGatherTimer=setTimeout(q,e6)}),X.onLocalCandidate?.((K,B)=>{if(this.peerConnection!==X)return;if(!K)return;if(H)Y.push({candidate:K,sdpMid:B});else this.sendSignal({type:"ice",sessionId:this.currentSessionId,candidate:{candidate:K,sdpMid:B}},{queueIfClosed:!0})}),X.onStateChange?.((K)=>{if(this.peerConnection!==X)return;if(K==="failed"||K==="closed"||K==="disconnected"){if(this.onDataChannelStatus?.(!1),this.dataChannelDisconnectedAt===null)this.dataChannelDisconnectedAt=Date.now();this.clientIsForeground=!1,this.clientStateUpdatedAt=Date.now()}}),X.onDataChannel?.((K)=>{if(this.peerConnection!==X)return;console.log(`${_} onDataChannel fired — received remote data channel`),this.attachDataChannel(K)}),X}attachDataChannel(Z){if(console.log(`${_} attachDataChannel called`),this.dataChannel&&this.dataChannel!==Z)try{this.dataChannel.close?.()}catch{}this.dataChannel=Z,Z.onOpen?.(()=>{if(this.dataChannel!==Z)return;console.log(`${_} dataChannel onOpen fired`),this.onDataChannelStatus?.(!0),this.dataChannelDisconnectedAt=null,this.clientIsForeground=!0,this.clientStateUpdatedAt=Date.now(),this.awaitingStateSyncRequest=!0,this.startHeartbeatLoop(),this.sendHeartbeat("ping")}),Z.onClosed?.(()=>{if(this.dataChannel!==Z)return;if(console.log(`${_} dataChannel onClosed fired`),this.dataChannel=null,this.onDataChannelStatus?.(!1),this.stopHeartbeatLoop(),this.dataChannelDisconnectedAt===null)this.dataChannelDisconnectedAt=Date.now();this.clientIsForeground=!1,this.clientStateUpdatedAt=Date.now()}),Z.onError?.(($)=>{if(this.dataChannel!==Z)return;console.error(`${_} datachannel error: ${String($)}`),this.dataChannel=null}),Z.onMessage?.(($)=>{if(this.dataChannel!==Z)return;let Q=$===null?"null":typeof $==="object"?$.constructor?.name??"object":typeof $,X=Buffer.isBuffer($)?$.length:$ instanceof ArrayBuffer?$.byteLength:ArrayBuffer.isView($)?$.byteLength:typeof $==="string"?$.length:-1;console.log(`${_} dataChannel onMessage: type=${Q} len=${X}`),this.handleDataChannelMessage($)})}handleDataChannelMessage(Z){let $;if(Buffer.isBuffer(Z))$=Z;else if(typeof Z==="string")$=Buffer.from(Z,"binary");else if(Z instanceof ArrayBuffer)$=Buffer.from(Z);else if(ArrayBuffer.isView(Z))$=Buffer.from(Z.buffer,Z.byteOffset,Z.byteLength);else return;let Q;try{Q=S4($);let Y=X0(Q.type);if(Q.type!==F.heartbeat)console.log(`${_} ◀ RECV ${Y} ${y4(Q.type,Q.payload)}`)}catch(Y){console.error(`${_} wire decode failed: ${String(Y)} hex=${$.subarray(0,32).toString("hex")}`),this.sendWire(F.error,{code:"INVALID_WIRE_ENVELOPE",message:String(Y)});return}if(this.lastHeartbeatReceivedAt=Date.now(),Q.type===F.heartbeat){this.handleHeartbeatPayload(Q.payload);return}if(Q.type===F.fileChunk){this.ensureFileReceiver().handleChunk(Q.payload);return}let X=j4(Q);if(X.kind==="ignore")return;if(X.kind==="command")this.sendWire(F.commandAck,{commandId:X.commandId,ok:!0});if(X.envelope.type==="client_state")this.clientIsForeground=X.envelope.isForeground===!0,this.clientStateUpdatedAt=Date.now(),console.log(`${_} client_state foreground=${this.clientIsForeground} tab=${X.envelope.activeTab??"unknown"} conv=${X.envelope.activeConversationId??"none"}`);if(this.onLegacyEnvelope(X.envelope),X.envelope.type==="state_sync_request")this.resyncRequired=!1,this.awaitingStateSyncRequest=!1,this.flushOutboundQueue()}handleRemoteIce(Z){if(!this.currentSessionId)return;let $=w(Z.sessionId);if($&&$!==this.currentSessionId)return;if(!this.peerConnection||!this.remoteDescriptionApplied){this.enqueuePendingRemoteCandidate(Z.candidate,$??void 0);return}this.addRemoteCandidate(Z.candidate)}enqueuePendingRemoteCandidate(Z,$){if(this.pendingRemoteCandidates.length>=128)this.pendingRemoteCandidates.shift();this.pendingRemoteCandidates.push({sessionId:$,candidate:Z})}addRemoteCandidate(Z){let $=H7(Z);if(!$)return;try{this.peerConnection?.addRemoteCandidate?.($.candidate,$.sdpMid)}catch(Q){console.warn(`${_} addRemoteCandidate failed: ${String(Q)}`)}}flushPendingRemoteCandidates(){if(!this.peerConnection||!this.currentSessionId||this.pendingRemoteCandidates.length===0)return;let Z=this.pendingRemoteCandidates;this.pendingRemoteCandidates=[];for(let $ of Z){if($.sessionId&&$.sessionId!==this.currentSessionId)continue;this.addRemoteCandidate($.candidate)}}enqueuePendingSignal(Z){if(this.pendingSignalQueue.length>=Z7)this.pendingSignalQueue.shift();this.pendingSignalQueue.push(Z)}flushPendingSignalQueue(){if(!this.signalingWs||this.signalingWs.readyState!==uZ.OPEN)return;if(this.pendingSignalQueue.length>0)console.log(`${_} flushing queued signaling messages count=${this.pendingSignalQueue.length}`);while(this.pendingSignalQueue.length>0){let Z=this.pendingSignalQueue[0];try{this.signalingWs.send(JSON.stringify(Z)),this.pendingSignalQueue.shift()}catch($){console.warn(`${_} signaling queued send failed: ${String($)}`);return}}}sendSignal(Z,$={}){let Q=String(Z.type??"unknown"),X=typeof Z.requestId==="string"?Z.requestId:void 0,Y=typeof Z.code==="string"?Z.code:void 0,H=typeof Z.message==="string"?Z.message:void 0,V=Q==="error"?` requestId=${X??"n/a"} code=${Y??"n/a"} message=${H??"n/a"}`:"";if(!this.signalingWs||this.signalingWs.readyState!==uZ.OPEN){if($.queueIfClosed)this.enqueuePendingSignal(Z),console.warn(`${_} sendSignal queued type=${Q}${V} readyState=${this.signalingWs?.readyState??"null"}`);else console.warn(`${_} sendSignal DROPPED type=${Q}${V} readyState=${this.signalingWs?.readyState??"null"}`);return!1}try{return console.log(`${_} sendSignal type=${Q}${V}`),this.signalingWs.send(JSON.stringify(Z)),!0}catch(J){if($.queueIfClosed)this.enqueuePendingSignal(Z);return console.warn(`${_} signaling send failed: ${String(J)}`),!1}}sendWire(Z,$){if(this.shouldDropSnapshot(Z,$))return;let Q=X0(Z);if(Z!==F.heartbeat)console.log(`${_} ▶ SEND ${Q} ${y4(Z,$)}`);let X={type:Z,seq:this.outboundSeq++,ts:Date.now(),payload:$},Y=w4(X),H=Z===F.heartbeat||Z===F.error;if(this.dataChannel!==null&&(!this.awaitingStateSyncRequest||H)&&this.trySendDataChannelBytes(Y)){this.maybeTriggerPush(Z,$);return}if(Z===F.heartbeat)return;if(this.resyncRequired&&Z!==F.error)return;this.enqueueOutbound({bytes:Y,type:Z,payload:$}),this.maybeTriggerPush(Z,$)}trySendDataChannelBytes(Z){let $=this.dataChannel;if(!$)return console.log(`${_} trySend: no dataChannel`),!1;try{if(typeof $.sendMessageBinary==="function")return $.sendMessageBinary(Z),console.log(`${_} trySend: sendMessageBinary ${Z.length}B ok`),!0;if(typeof $.sendMessage==="function")return $.sendMessage(Z),console.log(`${_} trySend: sendMessage ${Z.length}B ok`),!0;if(typeof $.send==="function")return $.send(Z),console.log(`${_} trySend: send ${Z.length}B ok`),!0}catch(Q){return console.error(`${_} trySend error: ${String(Q)}`),!1}return console.warn(`${_} trySend: no send method available on channel`),!1}enqueueOutbound(Z){let $=Z.bytes.byteLength;if($>b4){this.markResyncRequired("Outbound item exceeded queue byte limit; full sync required.");return}if(this.isSnapshotWireType(Z.type)){let X=this.outboundQueue.findIndex((Y)=>Y.type===Z.type);if(X>=0){let Y=this.outboundQueue[X];this.outboundQueue[X]=Z,this.outboundQueueBytes=Math.max(0,this.outboundQueueBytes-Y.bytes.byteLength+$);return}}let Q=!1;while(this.outboundQueue.length>=d6||this.outboundQueueBytes+$>b4){let X=this.outboundQueue.findIndex((J)=>!this.isSnapshotWireType(J.type)),Y=X>=0?X:0,V=this.outboundQueue.splice(Y,1)[0];if(!V)break;this.outboundQueueBytes=Math.max(0,this.outboundQueueBytes-V.bytes.byteLength),Q=!0}if(Q){this.markResyncRequired("Outbound queue overflowed; full sync required.");return}this.outboundQueue.push(Z),this.outboundQueueBytes+=$}markResyncRequired(Z){if(this.resyncRequired)return;this.resyncRequired=!0,this.awaitingStateSyncRequest=!0,this.outboundQueue=[],this.outboundQueueBytes=0,this.sendWire(F.error,{code:"RESYNC_REQUIRED",message:Z})}flushOutboundQueue(){if(!this.dataChannel)return;if(this.awaitingStateSyncRequest)return;while(this.outboundQueue.length>0){let Z=this.outboundQueue[0];if(!this.trySendDataChannelBytes(Z.bytes))return;this.outboundQueue.shift(),this.outboundQueueBytes=Math.max(0,this.outboundQueueBytes-Z.bytes.byteLength)}}isSnapshotWireType(Z){return Z===F.snapshotAgents||Z===F.snapshotCron||Z===F.snapshotConversations}snapshotSignature(Z,$){if(!this.isSnapshotWireType(Z)||!$||typeof $!=="object")return null;let Q=$;if(Z===F.snapshotAgents)return JSON.stringify({agents:this.normalizeSnapshotValue(Array.isArray(Q.agents)?Q.agents:[])});if(Z===F.snapshotCron)return JSON.stringify({cronJobs:this.normalizeCronJobsForSignature(Q.cronJobs)});if(Z===F.snapshotConversations)return JSON.stringify({conversations:this.normalizeSnapshotValue(Array.isArray(Q.conversations)?Q.conversations:[])});return null}normalizeSnapshotValue(Z){if(Array.isArray(Z))return Z.map((Y)=>this.normalizeSnapshotValue(Y));if(!Z||typeof Z!=="object")return Z;let $=Z,Q={},X=Object.keys($).sort();for(let Y of X){if(Y==="timestamp"||Y==="lastUpdated"||Y==="runningElapsedMs"||Y==="nextRunAt")continue;Q[Y]=this.normalizeSnapshotValue($[Y])}return Q}normalizeCronJobsForSignature(Z){if(!Array.isArray(Z))return[];let $=[];for(let Q of Z){if(!Q||typeof Q!=="object")continue;let X=Q;$.push({id:this.normalizeSnapshotValue(X.id),name:this.normalizeSnapshotValue(X.name),enabled:X.enabled===!0,isRunning:X.isRunning===!0,agentId:this.normalizeSnapshotValue(X.agentId),agentName:this.normalizeSnapshotValue(X.agentName),agentEmoji:this.normalizeSnapshotValue(X.agentEmoji),schedule:this.normalizeSnapshotValue(X.schedule),lastRunAt:this.normalizeSnapshotValue(X.lastRunAt),lastRunStatus:this.normalizeSnapshotValue(X.lastRunStatus),lastRunSummary:this.normalizeSnapshotValue(X.lastRunSummary)})}return $.sort((Q,X)=>String(Q.id??"").localeCompare(String(X.id??""))),$}shouldDropSnapshot(Z,$){let Q=this.snapshotSignature(Z,$);if(!Q)return!1;let X=Date.now(),Y=this.lastSnapshotSignatureByType.get(Z),H=this.lastSnapshotSentAtByType.get(Z)??0;if(Z===F.snapshotCron&&H>0&&X-H<Q7)return!0;if(Y===Q&&X-H<$7)return!0;return this.lastSnapshotSignatureByType.set(Z,Q),this.lastSnapshotSentAtByType.set(Z,X),!1}streamKey(Z,$){return`${Z}:${$}`}handleLegacyStreamStart(Z){let $=this.streamKey(Z.conversationId,Z.messageId);this.streamTextByMessageId.set($,"");let Q=this.pendingStreamBatches.get($);if(Q?.timer)clearTimeout(Q.timer);this.pendingStreamBatches.delete($)}handleLegacyStreamToken(Z){if(!Z.token)return;let $=this.streamKey(Z.conversationId,Z.messageId),Q=this.streamTextByMessageId.get($)??"";this.streamTextByMessageId.set($,Q+Z.token);let X=this.pendingStreamBatches.get($);if(X){X.tokens+=Z.token;return}let Y={conversationId:Z.conversationId,messageId:Z.messageId,offset:Q.length,tokens:Z.token,timer:null};Y.timer=setTimeout(()=>{this.flushStreamBatch($)},s6),this.pendingStreamBatches.set($,Y)}handleLegacyStreamEnd(Z){let $=this.streamKey(Z.conversationId,Z.messageId);this.flushStreamBatch($);let Q=this.streamTextByMessageId.get($)??"",X=Z.body&&Z.body.length>0?Z.body:Q;this.streamTextByMessageId.delete($),this.pendingStreamBatches.delete($),this.sendWire(F.streamEnd,{conversationId:Z.conversationId,messageId:Z.messageId,finalContent:X})}flushStreamBatch(Z){let $=this.pendingStreamBatches.get(Z);if(!$)return;if($.timer)clearTimeout($.timer),$.timer=null;if($.tokens.length>0)this.sendWire(F.streamBatch,{conversationId:$.conversationId,messageId:$.messageId,offset:$.offset,tokens:$.tokens});this.pendingStreamBatches.delete(Z)}flushAllStreamBatches(){for(let Z of Array.from(this.pendingStreamBatches.keys()))this.flushStreamBatch(Z)}sendHeartbeat(Z,$){console.log(`${_} sendHeartbeat kind=${Z}`),this.sendWire(F.heartbeat,{kind:Z,sentAt:$??Date.now()})}handleHeartbeatPayload(Z){let $=w(Z.kind),Q=Z.sentAt,X=typeof Q==="number"&&Number.isFinite(Q)?Q:typeof Q==="bigint"?Number(Q):Date.now();if($==="ping"){this.sendHeartbeat("pong",X);return}if($==="pong"){this.lastHeartbeatRttMs=Math.max(0,Date.now()-X);return}}startHeartbeatLoop(){this.stopHeartbeatLoop(),this.lastHeartbeatReceivedAt=Date.now(),this.heartbeatInterval=setInterval(()=>{if(!this.dataChannel)return;if(Date.now()-this.lastHeartbeatReceivedAt>n6){console.warn(`${_} heartbeat stale (rtt=${this.lastHeartbeatRttMs??-1}ms), closing peer`),this.closePeerConnection(),this.onDataChannelStatus?.(!1),this.dataChannelDisconnectedAt=Date.now(),this.clientIsForeground=!1,this.clientStateUpdatedAt=Date.now();return}this.sendHeartbeat("ping")},o6)}stopHeartbeatLoop(){if(this.heartbeatInterval)clearInterval(this.heartbeatInterval),this.heartbeatInterval=null}pushPriority(Z){if(Z===F.error)return 5;if(Z===F.streamEnd)return 4;if(Z===F.conversationDelta)return 3;if(Z===F.agentStatus)return 1;return 0}queuePushTrigger(Z,$){let Q=this.pushPriority(Z),X=this.pendingPushRequest;if(!X||Q>=X.priority)this.pendingPushRequest={type:Z,pushInfo:$,priority:Q};if(this.pendingPushTimer)return;this.pendingPushTimer=setTimeout(()=>{this.flushPendingPush()},r6)}async flushPendingPush(){this.pendingPushTimer=null;let Z=this.pendingPushRequest;if(this.pendingPushRequest=null,!Z)return;let $=Date.now(),Q=$-this.lastPushSentAt;if(Q<f4){this.pendingPushRequest=Z,this.pendingPushTimer=setTimeout(()=>{this.flushPendingPush()},f4-Q);return}this.lastPushSentAt=$;try{let X=await fetch(`${this.account.workerUrl}/api/push`,{method:"POST",headers:{"content-type":"application/json",authorization:`BotMobilePush ${this.account.pushSecret}`},body:JSON.stringify(Z.pushInfo)});if(!X.ok){let H=(await X.text().catch(()=>"")).trim();console.warn(`${_} push trigger failed status=${X.status}${H?` body=${H.slice(0,200)}`:""}`)}else console.log(`${_} push triggered type=${X0(Z.type)} foreground=${this.clientIsForeground??"unknown"} stateAgeMs=${$-this.clientStateUpdatedAt}`)}catch(X){console.warn(`${_} push trigger error=${String(X)}`)}}async maybeTriggerPush(Z,$){let Q=this.pushInfoForEvent(Z,$);if(!Q)return;if(!this.account.pushSecret||this.account.pushSecret.trim().length===0)return;let X=Date.now(),Y=this.dataChannelDisconnectedAt!==null?X-this.dataChannelDisconnectedAt:null,H=Y!==null&&Y>=i6;if(this.clientIsForeground!==!1&&!H){console.log(`${_} push skipped type=${X0(Z)} foreground=${this.clientIsForeground??"unknown"} disconnectedForMs=${Y??-1}`);return}this.queuePushTrigger(Z,Q)}normalizedPushAgentName(Z){if(typeof Z!=="string")return null;let $=Z.trim();if(!$)return null;if($.toLowerCase().startsWith("conversation:"))return null;return $}pushTitleForConversation(Z,$){let Q=this.normalizedPushAgentName($);if(Q)return Q;if(Z){let X=o0(Z),Y=this.normalizedPushAgentName(X?.agent?.name);if(Y)return Y}return"Assistant"}pushInfoForEvent(Z,$){if(Z===F.error){let Q=$;return{title:"BotMobile error",body:w(Q.message)??"An error occurred",data:{conversationId:w(Q.conversationId)??""}}}if(Z===F.agentStatus){let Q=$;if(Q.isRunning===!1)return{title:"Agent update",body:"An agent run finished while you were away.",data:{agentId:w(Q.id)??""}}}if(Z===F.conversationDelta){let Q=$,X=w(Q.id)??"",Y=Q.agent;if(Array.isArray(Q.messages)&&Q.messages.length>0){let H=Q.messages[Q.messages.length-1];if(H.role==="bot"){let V=w(H.content)??"",J=V.length>120?V.slice(0,120)+"…":V;return{title:this.pushTitleForConversation(X,Y?.name),body:J||"You have a new message.",data:{conversationId:X}}}}}if(Z===F.streamEnd){let Q=$,X=w(Q.conversationId)??"",Y=w(Q.finalContent)??"",H=Y.length>120?Y.slice(0,120)+"…":Y;return{title:this.pushTitleForConversation(X),body:H||"You have a new message.",data:{conversationId:X}}}return null}ensureFileReceiver(){if(!this._fileReceiver)this._fileReceiver=new Y3((Z,$)=>{this.sendWire(Z,$)});return this._fileReceiver}closePeerConnection(){if(this.answerGatherTimer)clearTimeout(this.answerGatherTimer),this.answerGatherTimer=null;this.stopHeartbeatLoop(),this.flushAllStreamBatches();try{this.dataChannel?.close?.()}catch{}try{this.peerConnection?.close?.()}catch{}this.dataChannel=null,this.peerConnection=null,this.remoteDescriptionApplied=!1,this.currentSessionId=null,this.currentOfferRequestId=null,this.pendingRemoteCandidates=[],this.awaitingStateSyncRequest=!0,this.lastSnapshotSignatureByType.clear(),this.lastSnapshotSentAtByType.clear()}cleanup(){if(this.pendingPushTimer)clearTimeout(this.pendingPushTimer),this.pendingPushTimer=null;if(this.stopSignalingHeartbeat(),this.pendingPushRequest=null,this.closePeerConnection(),this.pendingSignalQueue=[],this.streamTextByMessageId.clear(),this.pendingStreamBatches.clear(),this.lastSnapshotSignatureByType.clear(),this.lastSnapshotSentAtByType.clear(),this._fileReceiver)this._fileReceiver.dispose(),this._fileReceiver=null;if(this.signalingWs){try{this.signalingWs.close()}catch{}this.signalingWs=null}this.onSignalingStatus?.(!1),this.onDataChannelStatus?.(!1)}}var _="[botmobile:webrtc]",l6=30000,T4=1000,d6=1000,b4=10485760,f4=1000,i6=5000,r6=600,s6=50,o6=15000,n6=45000,t6=15000,a6=45000,e6=500,Z7=256,$7=2000,Q7=1e4,W0=null,I4=!1;var u4=KZ(()=>{C4();Q0();h4()});import V3 from"node:fs";import D7 from"node:os";import m4 from"node:path";function VZ(Z){if(typeof Z!=="string")return null;let $=Z.trim().toLowerCase();return $.length>0?$:null}function mZ(Z){if(typeof Z!=="string")return;let $=Z.trim();return $.length>0?$:void 0}function N0(Z){if(typeof Z!=="string")return;let $=Z.trim();return $.length>0?$:void 0}function gZ(Z){if(typeof Z==="number"&&Number.isFinite(Z)&&Z>0)return Math.floor(Z);return Date.now()}function F7(){try{V3.mkdirSync(v4,{recursive:!0})}catch(Z){console.warn(`${g4} failed creating state dir ${v4}: ${String(Z)}`)}}function _7(Z){i.version=J3,i.updatedAt=typeof Z.updatedAt==="number"&&Number.isFinite(Z.updatedAt)?Math.max(0,Math.floor(Z.updatedAt)):0,i.agents={};for(let[$,Q]of Object.entries(Z.agents??{})){let X=VZ($)??VZ(Q.id),Y=mZ(Q.name);if(!X||!Y)continue;i.agents[X]={id:X,name:Y,emoji:N0(Q.emoji),updatedAt:gZ(Q.updatedAt)}}i.cronJobs={};for(let[$,Q]of Object.entries(Z.cronJobs??{})){let X=VZ($)??VZ(Q.id);if(!X)continue;let Y=VZ(Q.agentId??void 0)??void 0;i.cronJobs[X]={id:X,name:mZ(Q.name),agentId:Y,agentName:mZ(Q.agentName),agentEmoji:N0(Q.agentEmoji),enabled:typeof Q.enabled==="boolean"?Q.enabled:void 0,updatedAt:gZ(Q.updatedAt),lastSeenAt:typeof Q.lastSeenAt==="number"&&Number.isFinite(Q.lastSeenAt)?Math.max(0,Math.floor(Q.lastSeenAt)):void 0,deletedAt:typeof Q.deletedAt==="number"&&Number.isFinite(Q.deletedAt)?Math.max(0,Math.floor(Q.deletedAt)):void 0}}}function G7(){p4=!0;try{let Z=V3.readFileSync(z0,"utf8"),$=JSON.parse(Z);if(!$||typeof $!=="object")return;if($.version!==J3)return;_7($)}catch{}}function kZ(){if(p4)return;G7()}function c4(){if(!CZ)return;if(vZ)return;vZ=setTimeout(()=>{vZ=null,l4()},U7)}function l4(){if(kZ(),!CZ)return;F7(),i.updatedAt=Date.now();try{let Z=JSON.stringify(i,null,2);V3.writeFileSync(z0,`${Z}
9
- `,"utf8"),CZ=!1}catch(Z){console.warn(`${g4} failed writing state ${z0}: ${String(Z)}`)}}function d4(){CZ=!0,c4()}function i4(){kZ()}function r4(){if(vZ)clearTimeout(vZ),vZ=null;l4()}function s4(Z){kZ();let $=VZ(Z.id),Q=mZ(Z.name);if(!$||!Q)return;let X=i.agents[$],Y={id:$,name:Q,emoji:N0(Z.emoji)??X?.emoji,updatedAt:gZ(Z.updatedAt)};if(!(!X||X.name!==Y.name||X.emoji!==Y.emoji||X.updatedAt!==Y.updatedAt))return;i.agents[$]=Y,d4()}function o4(Z){kZ();let $=VZ(Z);if(!$)return;return i.agents[$]}function E0(Z){kZ();let $=VZ(Z.id);if(!$)return;let Q=i.cronJobs[$],X={id:$,name:mZ(Z.name)??Q?.name,agentId:VZ(Z.agentId)??Q?.agentId,agentName:mZ(Z.agentName)??Q?.agentName,agentEmoji:N0(Z.agentEmoji)??Q?.agentEmoji,enabled:typeof Z.enabled==="boolean"?Z.enabled:Q?.enabled,updatedAt:gZ(Z.updatedAt),lastSeenAt:Z.lastSeenAt!==void 0?gZ(Z.lastSeenAt):Q?.lastSeenAt,deletedAt:Z.deletedAt!==void 0?gZ(Z.deletedAt):Q?.deletedAt};if(!(!Q||Q.name!==X.name||Q.agentId!==X.agentId||Q.agentName!==X.agentName||Q.agentEmoji!==X.agentEmoji||Q.enabled!==X.enabled||Q.updatedAt!==X.updatedAt||Q.lastSeenAt!==X.lastSeenAt||Q.deletedAt!==X.deletedAt))return;i.cronJobs[$]=X,d4()}function q3(Z){kZ();let $=VZ(Z);if(!$)return;return i.cronJobs[$]}function K3(Z){kZ();let $=Date.now(),Q=new Set;for(let X of Z){let Y=VZ(X);if(!Y)continue;Q.add(Y);let H=i.cronJobs[Y];if(!H)continue;if(H.lastSeenAt===$&&H.deletedAt===void 0)continue;H.lastSeenAt=$,H.deletedAt=void 0,H.updatedAt=Math.max(H.updatedAt,$),CZ=!0}for(let[X,Y]of Object.entries(i.cronJobs)){if(Q.has(X))continue;if(Y.deletedAt)continue;Y.deletedAt=$,Y.updatedAt=Math.max(Y.updatedAt,$),CZ=!0}if(CZ)c4()}var g4="[botmobile:cache]",J3=1,U7=1000,z0,v4,p4=!1,CZ=!1,vZ=null,i;var n4=KZ(()=>{z0=m4.join(D7.homedir(),".openclaw","botmobile","state.json"),v4=m4.dirname(z0),i={version:J3,updatedAt:0,agents:{},cronJobs:{}}});var _5={};x5(_5,{wsRelay:()=>k,monitorBotMobileProvider:()=>F5,handleToolHookEvent:()=>C0,handleAgentRunHookEnd:()=>C3,getFileWatcherCount:()=>U8,bindSessionToConversation:()=>M3});import W7 from"node:dns";import{watch as O3,statSync as S0,readFileSync as j3}from"node:fs";import UZ from"node:path";import iZ from"node:os";import{createReplyPrefixOptions as z7}from"openclaw/plugin-sdk";function k(Z,$){if($?.record!==!1)Y4(Z);if(LZ)LZ.sendLegacyEnvelope(Z);return!0}function x7(Z,$){return SZ(Z,$).name}function h7(Z,$){return SZ(Z,$).emoji}function SZ(Z,$){let Q=bZ(Z,$),X=o4($),Y=Q.name;if((Q.source==="agent-id"||!Y||Y===$)&&X?.name)Y=X.name;let H=Q.emoji??X?.emoji;return s4({id:$,name:Y,emoji:H,updatedAt:Date.now()}),{name:Y,emoji:H}}function H5(Z){return{resolveAgentDisplay:({agentId:$})=>SZ(Z,$),resolveCronSnapshot:($)=>{let Q=q3($);if(!Q)return;return{name:Q.name,agentId:Q.agentId,agentName:Q.agentName,agentEmoji:Q.agentEmoji}}}}function pZ(Z){if(!Array.isArray(Z))return;return Z.map((Q)=>typeof Q==="string"?Q.trim():"").filter((Q)=>Q.length>0)}function T7(Z){let $=new Set,Q=[];for(let X of Z){let Y=X.trim();if(!Y)continue;if($.has(Y))continue;$.add(Y),Q.push(Y)}return Q.length>0?Q:void 0}function b7(Z){if(!Z)return{};let $=Z.trim();if(!$)return{};let Q=$.indexOf("/");if(Q<0)return{model:$};let X=$.slice(0,Q).trim(),Y=$.slice(Q+1).trim();return{provider:X||void 0,model:Y||void 0}}function f7(Z){let $=Z?.trim().toLowerCase();if(!$)return;switch($){case"anthropic":return"ANTHROPIC_API_KEY";case"openai":return"OPENAI_API_KEY";case"gemini":case"google":return"GEMINI_API_KEY";case"openrouter":return"OPENROUTER_API_KEY";case"xai":return"XAI_API_KEY";case"groq":return"GROQ_API_KEY";case"perplexity":return"PERPLEXITY_API_KEY";case"deepseek":return"DEEPSEEK_API_KEY";case"mistral":return"MISTRAL_API_KEY";case"cohere":return"COHERE_API_KEY";default:return}}function y(Z){let $=Z.replace(/\s+/g," ").trim();if(!$)return"working";if($.length<=t4)return $;return`${$.slice(0,t4-3).trimEnd()}...`}function j0(Z){if(!Z)return;let $=Z.trim();return $.length>0?$:void 0}function P3(Z){if(!Z)return;let $=Z.trim();return $.length>0?$:void 0}function I7(Z){let $=Z.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[._-]+/g," ").replace(/\s+/g," ").trim().toLowerCase();if(!$)return"running tool";return y(`running ${$}`)}function o(Z){if(!Z)return;let $=Z.replace(/\s+/g," ").trim();if(!$)return;if($.length<=e4)return $;return`${$.slice(0,e4-1).trimEnd()}…`}function e(Z,$){if(!Z)return;for(let Q of $){let X=Z[Q];if(typeof X==="string"&&X.trim().length>0)return X.trim()}return}function y7(Z){if(!Z)return;let $=Z.trim().split(/\s+/)[0];if(!$)return;if($.startsWith("/")){let Q=$.split("/");return Q[Q.length-1]||$}return $}function u7(Z){if(!Z)return;try{let $=new URL(Z).hostname;return $?o($):void 0}catch{return o(Z)}}function v7(Z){let $=e(Z,["action","op","operation","method"]);return o($)}function $Z(Z,$){if(!$)return y(Z);return y(`${Z} (${$})`)}function m7(Z,$){let Q=Z.trim().toLowerCase(),X=v7($);if(Q==="web_search"){let Y=o(e($,["query","q","text"]));return $Z("searching the web",Y)}if(Q==="web_fetch"){let Y=u7(e($,["url"]));return $Z("fetching webpage",Y)}if(Q==="browser"){let Y=o(e($,["url","selector","query","text"]));if(X&&Y)return y(`browser ${X} (${Y})`);if(X)return y(`browser ${X}`);return $Z("using browser tool",Y)}if(Q==="memory_search"){let Y=o(e($,["query","q","text"]));return $Z("searching memory",Y)}if(Q==="memory_get"){let Y=o(e($,["id","key","name"]));return $Z("reading memory entry",Y)}if(Q==="sessions_history"){let Y=o(e($,["sessionId","sessionKey","id"]));return $Z("reading session history",Y)}if(Q==="sessions_list")return y("listing sessions");if(Q==="sessions_send"){let Y=o(e($,["sessionId","sessionKey","to","target"]));return $Z("sending cross-session message",Y)}if(Q==="sessions_spawn"){let Y=o(e($,["name","label","agentId"]));return $Z("starting helper session",Y)}if(Q==="cron"){if(X)return y(`updating scheduled task (${X})`);return y("updating scheduled task")}if(Q==="message"){if(X)return y(`preparing message action (${X})`);return y("preparing message")}if(Q==="gateway"){if(X)return y(`checking gateway (${X})`);return y("checking gateway")}if(Q==="canvas"){if(X)return y(`updating canvas (${X})`);return y("updating canvas")}if(Q==="nodes"){if(X)return y(`running node action (${X})`);return y("running node action")}if(Q==="image"){if(X)return y(`working with image (${X})`);return y("working with image")}if(Q==="tts")return y("generating audio");if(Q==="exec_command"){let Y=e($,["cmd","command"]),H=o(y7(Y));return $Z("running terminal command",H)}if(Q==="write_stdin")return y("continuing terminal command");if(Q==="search_query"){let Y=o(e($,["q","query"]));return $Z("searching",Y)}if(Q==="open"){let Y=o(e($,["ref_id","refId","url"]));return $Z("opening reference",Y)}if(Q==="click")return y("opening linked reference");if(Q==="find"){let Y=o(e($,["pattern","text"]));return $Z("finding text",Y)}if(Q==="apply_patch")return y("editing code");return I7(Z)}function V5(Z,$){return`${Z}::${$??"__unknown__"}`}function g7(Z=Date.now()){for(let[$,Q]of rZ)if(Z-Q.updatedAt>w7)rZ.delete($)}function p7(Z){let $=j0(Z);if(!$)return;let Q=rZ.get($);if(Q)return Q.updatedAt=Date.now(),Q.conversationId;let X=$.match(C7);if(X&&X[1]?.trim())return R(X[1]);let Y=$.match(k7);if(Y&&Y[1]?.trim())return R(Y[1]);let H=$.match(A7);if(H&&H[1]?.trim())return`cron:${H[1].trim().toLowerCase()}`;return}function R3(Z){let $,Q=-1,X=`${Z}::`;for(let[Y,H]of JZ){if(!Y.startsWith(X))continue;if(H.tools.length===0)continue;if(H.updatedAt>Q)Q=H.updatedAt,$=Y}if($)return DZ.set(Z,$),$;DZ.delete(Z);return}function c7(Z,$){if($){let X=V5(Z,$);if(JZ.delete(X),DZ.get(Z)===X)R3(Z);return}let Q=`${Z}::`;for(let X of Array.from(JZ.keys())){if(!X.startsWith(Q))continue;JZ.delete(X)}DZ.delete(Z)}function M3(Z){let $=j0(Z.sessionKey);if(!$)return;let Q=R(Z.conversationId);if(!Q)return;g7(),rZ.set($,{conversationId:Q,updatedAt:Date.now()})}function C0(Z){let $=P3(Z.agentId),Q=P3(Z.toolName);if(!$||!Q)return;let X=Date.now(),Y=j0(Z.sessionKey),H=V5($,Y),V=p7(Y),J=wZ.get($)?.status,q=JZ.get(H)??{agentId:$,sessionKey:Y,conversationId:V,tools:[],updatedAt:X};if(q.updatedAt=X,V)q.conversationId=V;if(Z.phase==="start"){let D=m7(Q,Z.toolParams);if(q.tools.push({name:Q,activity:D}),JZ.set(H,q),DZ.set($,H),J!=="working")xZ.add($);AZ($,"working",{activeConversationId:V,activeTool:D},Z.config),console.log(`${a4} before_tool_call agent=${$} tool=${Q} activity="${D}" session=${Y??"-"} conv=${V??"-"} depth=${q.tools.length}`);return}let K=!1;for(let D=q.tools.length-1;D>=0;D-=1){if(q.tools[D]?.name!==Q)continue;q.tools.splice(D,1),K=!0;break}if(!K&&q.tools.length>0)q.tools.pop();if(q.tools.length===0){if(JZ.delete(H),DZ.get($)===H)R3($)}else JZ.set(H,q),DZ.set($,H);let B=DZ.get($)??R3($),O=B?JZ.get(B):void 0,L=O?.tools[O.tools.length-1];if(L)AZ($,"working",{activeConversationId:O?.conversationId,activeTool:L.activity},Z.config);else if(xZ.has($))xZ.delete($),AZ($,"idle",{activeTool:void 0,activeConversationId:void 0},Z.config);else AZ($,"working",{activeTool:z3,activeConversationId:O?.conversationId},Z.config);console.log(`${a4} after_tool_call agent=${$} tool=${Q} session=${Y??"-"} conv=${V??"-"} depth=${q.tools.length} next="${L?.activity??z3}" error=${Z.error?"yes":"no"}`)}function C3(Z){let $=P3(Z.agentId);if(!$)return;let Q=j0(Z.sessionKey);if(c7($,Q),!xZ.has($))return;xZ.delete($),AZ($,"idle",{activeConversationId:void 0,activeTool:void 0,errorMessage:Z.success===!1?Z.error:void 0},Z.config)}function l7(Z){let $=["token","apiKey","key","accessToken","refreshToken","secret"];for(let Q of $){let X=Z[Q];if(typeof X==="string"&&X.trim().length>0)return!0}return!1}function d7(Z,$){let Q=$?.trim().toLowerCase();if(!Q)return!1;let X=UZ.join(iZ.homedir(),".openclaw","agents",Z,"agent","auth-profiles.json");try{let Y=S0(X),H=F3.get(Z);if(H&&H.mtimeMs===Y.mtimeMs&&H.size===Y.size)return H.hasCredentialByProvider[Q]===!0;let V=j3(X,"utf8"),q=JSON.parse(V)?.profiles,K={};if(q&&typeof q==="object")for(let B of Object.values(q)){if(!B||typeof B!=="object")continue;let O=B,L=g(O.provider)?.toLowerCase();if(!L)continue;if(l7(O))K[L]=!0;else if(K[L]!==!0)K[L]=!1}return F3.set(Z,{mtimeMs:Y.mtimeMs,size:Y.size,hasCredentialByProvider:K}),K[Q]===!0}catch{return F3.delete(Z),!1}}function i7(Z,$){let Q=f7(Z),X=d7($,Z);if(!Q&&!X)return{};return{envName:Q,present:X}}function J5(Z,$){let Q=Z.agents,X=Q&&typeof Q.defaults==="object"&&Q.defaults?Q.defaults:{},H=(Array.isArray(Q?.list)?Q.list:[]).find((d)=>typeof d?.id==="string"&&d.id===$)??{},V=typeof H.model==="string"?H.model:typeof H.model?.primary==="string"?H.model.primary:typeof X.model?.primary==="string"?X.model.primary:void 0,J=typeof V==="string"?V.trim():"",q=b7(J),K=typeof H.workspace==="string"?H.workspace:typeof X.workspace==="string"?X.workspace:void 0,B=typeof K==="string"&&K.trim().length>0?K.trim():void 0,O=L5($),L=pZ(H.skills)??pZ(X.skills)??O?.skills,D=pZ(H.tools?.allow)??pZ(X.tools?.allow),U=pZ(H.tools?.deny)??pZ(X.tools?.deny),z=typeof H.contextTokens==="number"?H.contextTokens:X.contextTokens,N=typeof z==="number"&&Number.isFinite(z)?Math.max(0,Math.floor(z)):O?.contextTokens,G=typeof H.timeoutSeconds==="number"?H.timeoutSeconds:X.timeoutSeconds,T=typeof G==="number"&&Number.isFinite(G)?Math.max(0,Math.floor(G)):void 0,A=typeof H.maxConcurrent==="number"?H.maxConcurrent:X.maxConcurrent,p=typeof A==="number"&&Number.isFinite(A)?Math.max(0,Math.floor(A)):void 0,b=typeof H.typingMode==="string"?H.typingMode:X.typingMode,S=typeof b==="string"&&b.trim().length>0?b.trim():void 0,c=q.provider??O?.modelProvider,j=q.model??O?.model,E=B??O?.promptWorkspace,v=typeof N==="number"&&typeof O?.totalTokens==="number"?Math.max(0,N-Math.max(0,Math.floor(O.totalTokens))):void 0,W=typeof N==="number"&&N>0&&typeof O?.totalTokens==="number"?Math.min(1,Math.max(0,O.totalTokens/N)):void 0,m=i7(c,$),x=e7($,O),l={model:j,provider:c,workspace:E,skills:L,skillDetails:O?.skillDetails,toolsAllow:D,toolsDeny:U,contextTokens:N,contextRemainingTokens:v,contextUsageRatio:W,timeoutSeconds:T,maxConcurrent:p,typingMode:S,sessionId:O?.sessionId,sessionUpdatedAt:O?.updatedAt,sessionInputTokens:O?.inputTokens,sessionOutputTokens:O?.outputTokens,sessionTotalTokens:O?.totalTokens,usageEventCount:x?.usageEventCount,usageInputTokens:x?.usageInputTokens,usageOutputTokens:x?.usageOutputTokens,usageCacheReadTokens:x?.usageCacheReadTokens,usageCacheWriteTokens:x?.usageCacheWriteTokens,usageTotalTokens:x?.usageTotalTokens,usageTotalCostUsd:x?.usageTotalCostUsd,usageUpdatedAt:x?.usageUpdatedAt,historySessionCount:O?.historySessionCount,historyInputTokens:O?.historyInputTokens,historyOutputTokens:O?.historyOutputTokens,historyTotalTokens:O?.historyTotalTokens,historyUpdatedAt:O?.historyUpdatedAt,promptSource:O?.promptSource,promptGeneratedAt:O?.promptGeneratedAt,providerKeyEnv:m.envName,providerKeyPresent:m.present},n=q5(l);return l.accountStatus=n.status,l.accountStatusReason=n.reason,Object.values(l).some((d)=>d!==void 0)?l:void 0}function q5(Z){if(Z.providerKeyPresent===!1)return{status:"missing_credentials",reason:Z.providerKeyEnv?`No provider credentials detected (${Z.providerKeyEnv} not set)`:"No provider credentials detected"};if(Z.providerKeyPresent===!0)return{status:"ready",reason:"Provider credentials detected"};return{status:"unknown",reason:Z.provider?"Provider configured":"Provider unknown"}}function K5(Z,$,Q){if(!Z&&$!=="error")return Z;let X={...Z??{}};if($==="error")X.accountStatus="error",X.accountStatusReason=g(Q)??X.accountStatusReason??"Agent runtime error";else{let H=q5(X);X.accountStatus=H.status,X.accountStatusReason=H.reason}return Object.values(X).some((H)=>H!==void 0)?X:void 0}function C(Z){if(typeof Z!=="number"||!Number.isFinite(Z))return;return Z}function r7(Z){return typeof Z==="boolean"?Z:void 0}function g(Z){if(typeof Z!=="string")return;let $=Z.trim();return $.length>0?$:void 0}function s7(Z){if(!Z||typeof Z!=="object")return;let $=Z,Q=g($.name);if(!Q)return;return{name:Q,description:g($.description),source:g($.source),filePath:g($.filePath),baseDir:g($.baseDir),disableModelInvocation:r7($.disableModelInvocation)}}function O5(){return{eventCount:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,totalTokens:0,totalCostUsd:0,updatedAt:0}}function o7(Z){return{eventCount:Math.max(0,Math.floor(Z?.usageEventCount??0)),inputTokens:Math.max(0,Math.floor(Z?.usageInputTokens??0)),outputTokens:Math.max(0,Math.floor(Z?.usageOutputTokens??0)),cacheReadTokens:Math.max(0,Math.floor(Z?.usageCacheReadTokens??0)),cacheWriteTokens:Math.max(0,Math.floor(Z?.usageCacheWriteTokens??0)),totalTokens:Math.max(0,Math.floor(Z?.usageTotalTokens??0)),totalCostUsd:Math.max(0,C(Z?.usageTotalCostUsd)??0),updatedAt:Math.max(0,Math.floor(Z?.usageUpdatedAt??0))}}function B5(Z){if(Z.eventCount<=0)return;return{usageEventCount:Z.eventCount,usageInputTokens:Z.inputTokens,usageOutputTokens:Z.outputTokens,usageCacheReadTokens:Z.cacheReadTokens,usageCacheWriteTokens:Z.cacheWriteTokens,usageTotalTokens:Z.totalTokens,usageTotalCostUsd:Number(Z.totalCostUsd.toFixed(6)),usageUpdatedAt:Z.updatedAt>0?Z.updatedAt:void 0}}function w3(Z){if(typeof Z==="number"&&Number.isFinite(Z)&&Z>0){if(Z>=1000000000000)return Math.floor(Z);if(Z>=1e9)return Math.floor(Z*1000);return Math.floor(Z)}if(typeof Z==="string"&&Z.trim().length>0){let $=Number(Z);if(Number.isFinite($)&&$>0)return w3($);let Q=Date.parse(Z);if(Number.isFinite(Q)&&Q>0)return Math.floor(Q)}return 0}function n7(Z){if(!Z.includes('"usage"'))return;try{let $=JSON.parse(Z),Q=$.message;if(!Q||typeof Q!=="object")return;let X=Q.usage;if(!X||typeof X!=="object")return;let Y=X,H=Math.max(0,Math.floor(C(Y.input)??C(Y.inputTokens)??C(Y.input_tokens)??0)),V=Math.max(0,Math.floor(C(Y.output)??C(Y.outputTokens)??C(Y.output_tokens)??0)),J=Math.max(0,Math.floor(C(Y.cacheRead)??C(Y.cacheReadTokens)??C(Y.cache_read_tokens)??0)),q=Math.max(0,Math.floor(C(Y.cacheWrite)??C(Y.cacheWriteTokens)??C(Y.cache_write_tokens)??0)),K=H+V+J+q,B=Math.max(0,Math.floor(C(Y.totalTokens)??C(Y.total_tokens)??K)),O=Y.cost,L=O&&typeof O==="object"?O:void 0,D=Math.max(0,C(Y.totalCostUsd)??C(Y.total_cost_usd)??C(L?.total)??0),U=Math.max(w3(Q.timestamp),w3($.timestamp));return{eventCount:1,inputTokens:H,outputTokens:V,cacheReadTokens:J,cacheWriteTokens:q,totalTokens:B,totalCostUsd:D,updatedAt:U}}catch{return}}function t7(Z,$){if(UZ.isAbsolute($))return $;return UZ.join(iZ.homedir(),".openclaw","agents",Z,"sessions",$)}function a7(Z){try{let $=S0(Z),Q=U3.get(Z);if(Q&&Q.mtimeMs===$.mtimeMs&&Q.size===$.size)return Q.totals;let X=j3(Z,"utf8"),Y=O5(),H=X.split(/\r?\n/);for(let J of H){let q=J.trim();if(!q)continue;let K=n7(q);if(!K)continue;Y.eventCount+=K.eventCount,Y.inputTokens+=K.inputTokens,Y.outputTokens+=K.outputTokens,Y.cacheReadTokens+=K.cacheReadTokens,Y.cacheWriteTokens+=K.cacheWriteTokens,Y.totalTokens+=K.totalTokens,Y.totalCostUsd+=K.totalCostUsd,Y.updatedAt=Math.max(Y.updatedAt,K.updatedAt)}let V=B5(Y);return U3.set(Z,{mtimeMs:$.mtimeMs,size:$.size,totals:V}),V}catch{U3.delete(Z);return}}function e7(Z,$){let Q=Date.now(),X=D3.get(Z);if(X&&Q-X.refreshedAt<M7)return X.totals;let Y=$?.sessionFiles??[];if(Y.length===0){D3.set(Z,{refreshedAt:Q,totals:void 0});return}let H=O5(),V=new Set;for(let q of Y){let K=q.trim();if(!K||V.has(K))continue;V.add(K);let B=t7(Z,K),O=a7(B);if(!O)continue;let L=o7(O);H.eventCount+=L.eventCount,H.inputTokens+=L.inputTokens,H.outputTokens+=L.outputTokens,H.cacheReadTokens+=L.cacheReadTokens,H.cacheWriteTokens+=L.cacheWriteTokens,H.totalTokens+=L.totalTokens,H.totalCostUsd+=L.totalCostUsd,H.updatedAt=Math.max(H.updatedAt,L.updatedAt)}let J=B5(H);return D3.set(Z,{refreshedAt:Q,totals:J}),J}function L5(Z){let $=UZ.join(iZ.homedir(),".openclaw","agents",Z,"sessions","sessions.json");try{let Q=S0($),X=cZ.get(Z);if(X&&X.mtimeMs===Q.mtimeMs&&X.size===Q.size)return X.summary;let Y=j3($,"utf8"),H=JSON.parse(Y);if(!H||typeof H!=="object"){cZ.set(Z,{mtimeMs:Q.mtimeMs,size:Q.size,summary:void 0});return}let V,J,q=0,K=`agent:${Z}:`,B=0,O=0,L=0,D=0,U=0,z=new Set;for(let[E,v]of Object.entries(H)){if(!E.startsWith(K))continue;if(!v||typeof v!=="object")continue;let W=v,m=g(W.sessionFile);if(m)z.add(m);let x=C(W.updatedAt)??0;if(B+=1,U=Math.max(U,x),O+=Math.max(0,C(W.inputTokens)??0),L+=Math.max(0,C(W.outputTokens)??0),D+=Math.max(0,C(W.totalTokens)??0),!J||x>=q)V=E,J=W,q=x}if(!J){cZ.set(Z,{mtimeMs:Q.mtimeMs,size:Q.size,summary:void 0});return}let N=J.skillsSnapshot,T=(Array.isArray(N?.skills)?N?.skills:[]).map((E)=>{if(typeof E==="string")return g(E);if(!E||typeof E!=="object")return;return g(E.name)}).filter((E)=>typeof E==="string"),p=(Array.isArray(N?.resolvedSkills)?N.resolvedSkills:[]).map((E)=>s7(E)).filter((E)=>!!E),b=p.map((E)=>E.name),S=T7([...T,...b]),c=J.systemPromptReport,j={sessionKey:V,sessionId:g(J.sessionId),updatedAt:C(J.updatedAt),modelProvider:g(J.modelProvider),model:g(J.model),contextTokens:C(J.contextTokens),inputTokens:C(J.inputTokens),outputTokens:C(J.outputTokens),totalTokens:C(J.totalTokens),skillsCount:S?.length,skills:S,skillDetails:p.length>0?p:void 0,historySessionCount:B>0?B:void 0,historyInputTokens:O>0?O:void 0,historyOutputTokens:L>0?L:void 0,historyTotalTokens:D>0?D:void 0,historyUpdatedAt:U>0?U:void 0,promptSource:g(c?.source),promptGeneratedAt:C(c?.generatedAt),promptWorkspace:g(c?.workspaceDir),sessionFiles:z.size>0?Array.from(z):void 0};return cZ.set(Z,{mtimeMs:Q.mtimeMs,size:Q.size,summary:j}),j}catch{cZ.delete(Z);return}}function Z8(Z,$,Q){let X=SZ(Z,$),Y=L5($),H=Y?{...Y,sessionFileCount:Y.sessionFiles?.length,sessionFiles:void 0}:null,V={agentId:$,display:X,configDetails:Q??null,sessionSummary:H},J=JSON.stringify(V);if(E3.get($)===J)return;E3.set($,J),console.log(`${u} [agent-details] ${JSON.stringify(V,null,2)}`)}function $8(Z,$){if(!$)return Z;if(Z.startsWith($))return Z;return`${$} ${Z}`.trim()}function Q8(Z,$){let Q=g(Z);if(Q)return Q.slice(0,96);return(($.split(/\r?\n/,1)[0]?.trim()??"")||"Agent Task").slice(0,96)}function X8(Z){if(typeof Z!=="number"||!Number.isFinite(Z))return 3600000;return Math.max(60000,Math.min(2592000000,Math.floor(Z)))}function P0(Z){if(!Z)return;let $=Z.trim();if(!$)return;if($.startsWith("conversation:"))return;if($.toLowerCase()==="conversation")return;return R($)}function Y8(Z){let $=Z.agents?.list;if(!Array.isArray($))return new Set;let Q=new Set;for(let X of $){if(!X||typeof X!=="object")continue;let Y=typeof X.id==="string"?X.id.trim():"";if(!Y)continue;Q.add(Y)}return Q}function D5(Z,$){if(!$)return;let Q=$.trim();if(!Q)return;if(Q.startsWith("conversation:"))return;if(Q.toLowerCase()==="conversation")return;if(Q.includes(":"))return;let X=Y8(Z);if(X.size>0&&!X.has(Q))return;return Q}function $5(Z,$){let Q=Z.split(":");if(Q.length<2||Q[0]!=="agent")return Z;return Q[1]=$,Q.join(":")}function Q5(Z){let $=Z.trim();if(!$)return 0;return Math.max(1,Math.ceil($.length/4))}function H8(Z){if(Z==="error")return"error";if(Z==="skipped")return"skipped";return"ok"}function X5(Z,$){return`${Z}:${$??Date.now()}`}function V8(Z){let $=Z.agents?.list??[];if(!Array.isArray($))return[];let Q=new Set,X=Date.now(),Y=[];for(let H of $){let V=H?.id??"unknown";Q.add(V);let J=lZ.get(V),q=wZ.get(V),K=SZ(Z,V),B=J5(Z,V)??q?.details,O=q?.status??"idle",L={agentId:V,name:K.name,emoji:K.emoji??q?.emoji,color:q?.color,details:K5(B,O,q?.errorMessage),status:O,activeConversationId:P0(q?.activeConversationId),activeTool:q?.activeTool,activeElapsedMs:q?.activeElapsedMs,activeTokens:q?.activeTokens,sessionTokensIn:J?.in??q?.sessionTokensIn??0,sessionTokensOut:J?.out??q?.sessionTokensOut??0,lastActivityAt:q?.lastActivityAt??X,errorMessage:q?.errorMessage};wZ.set(V,L),Z8(Z,V,L.details),Y.push(L)}for(let H of Array.from(wZ.keys()))if(!Q.has(H))wZ.delete(H);return Y}function k0(Z){return V8(Z)}function AZ(Z,$,Q,X){let Y=!!Q&&Object.prototype.hasOwnProperty.call(Q,"activeConversationId"),H=!!Q&&Object.prototype.hasOwnProperty.call(Q,"activeTool"),V=!!Q&&Object.prototype.hasOwnProperty.call(Q,"activeTokens"),J=wZ.get(Z),q=lZ.get(Z),K=Date.now(),B=J?.name??(X?x7(X,Z):Z||"Assistant"),O=J?.emoji??(X?h7(X,Z):void 0),L=J?.details??(X?J5(X,Z):void 0),D=Q?.errorMessage??J?.errorMessage,U={agentId:Z,name:B,emoji:O,color:J?.color,details:K5(L,$,D),status:$,activeConversationId:Y?P0(Q?.activeConversationId):P0(J?.activeConversationId),activeTool:H?Q?.activeTool:J?.activeTool,activeElapsedMs:Q?.activeElapsedMs,activeTokens:V?Q?.activeTokens:J?.activeTokens,sessionTokensIn:q?.in??J?.sessionTokensIn??0,sessionTokensOut:q?.out??J?.sessionTokensOut??0,lastActivityAt:K,errorMessage:Q?.errorMessage};if($==="working"){if(!U.activeConversationId)U.activeConversationId=P0(J?.activeConversationId);if(!H&&!U.activeTool)U.activeTool=J?.activeTool;if(!V&&U.activeTokens===void 0)U.activeTokens=J?.activeTokens}else U.activeConversationId=void 0,U.activeTool=void 0,U.activeTokens=void 0;if($!=="error"&&Q?.errorMessage===void 0)U.errorMessage=void 0;wZ.set(Z,U),k({type:"agent_status",agentId:U.agentId,status:U.status,color:U.color,details:U.details,activeConversationId:U.activeConversationId,activeTool:U.activeTool,activeElapsedMs:U.activeElapsedMs,activeTokens:U.activeTokens,sessionTokensIn:U.sessionTokensIn,sessionTokensOut:U.sessionTokensOut,lastActivityAt:U.lastActivityAt,errorMessage:U.errorMessage})}function J8(Z){if(Z&&typeof Z==="object"){let $=Z;if($.kind==="at"&&typeof $.at==="string")return{kind:"at",at:$.at};if($.kind==="every"&&typeof $.everyMs==="number")return{kind:"every",everyMs:Math.max(1,Math.floor($.everyMs))};if($.kind==="cron"&&typeof $.expr==="string")return{kind:"cron",expr:$.expr,tz:typeof $.tz==="string"?$.tz:void 0}}return{kind:"every",everyMs:60000}}function U5(Z,$){return Z.map((Q)=>{let X=typeof Q.agentId==="string"&&Q.agentId.trim()?Q.agentId:void 0,Y=X?SZ($,X):void 0,H=Q.sessionTarget==="isolated"?"isolated":"main",V=Q.payload?.kind==="agentTurn"?"agentTurn":"systemEvent",J={id:Q.id,agentId:X,agentName:Y?.name,agentEmoji:Y?.emoji,name:Q.name??Q.id,enabled:Q.enabled!==!1,schedule:J8(Q.schedule),sessionTarget:H,payloadKind:V,lastRunAt:Q.state?.lastRunAtMs,lastRunStatus:Q.state?.lastStatus,lastRunDurationMs:Q.state?.lastDurationMs,lastRunSummary:void 0,nextRunAt:Q.state?.nextRunAtMs,isRunning:!!Q.state?.runningAtMs,runningElapsedMs:Q.state?.runningAtMs?Date.now()-Q.state.runningAtMs:void 0,runningTokens:void 0};return E0({id:J.id,name:J.name,agentId:J.agentId,agentName:J.agentName,agentEmoji:J.agentEmoji,enabled:J.enabled,updatedAt:Date.now(),lastSeenAt:Date.now(),deletedAt:void 0}),J})}function MZ(Z,$={}){let Q=Date.now(),X=$.includeDisabled??!0,Y=$.force===!0,H=p0(Z),V=X?H:H.filter((K)=>K.enabled!==!1),J=U5(V,Z),q=JSON.stringify(J.map((K)=>({id:K.id,agentId:K.agentId,name:K.name,enabled:K.enabled,schedule:K.schedule,sessionTarget:K.sessionTarget,payloadKind:K.payloadKind,lastRunAt:K.lastRunAt,lastRunStatus:K.lastRunStatus,isRunning:K.isRunning,runningTokens:K.runningTokens})));if(q===Z5){if(!Y)return;if(Q-L3<j7)return}if(!Y){if(Q-L3<S7)return}Z5=q,L3=Q,K3(J.map((K)=>K.id)),k({type:"cron_list",jobs:J})}function q8(Z){let $=p0(Z),Q=U5($,Z);return K3(Q.map((X)=>X.id)),{jobs:Q}}function Y5(Z,$){let Q=typeof $?.sinceTimestampMs==="number"&&Number.isFinite($.sinceTimestampMs)?$.sinceTimestampMs:void 0,X=typeof $?.stateBornAt==="number"&&Number.isFinite($.stateBornAt)?$.stateBornAt:void 0,Y=typeof $?.globalRevision==="number"&&Number.isFinite($.globalRevision)?$.globalRevision:void 0,H=n0({sinceTimestampMs:Q,stateBornAt:X,globalRevision:Y,conversations:$?.conversations,fallbackAgents:k0(Z),fallbackCronJobs:q8(Z).jobs});if(H.mode==="snapshot"){k({type:"state_snapshot",state:H.state},{record:!1});return}k({type:"state_delta",state:H.state,sinceTimestampMs:Q},{record:!1})}function K8(Z,$){if($.action==="started")k({type:"cron_run_started",jobId:$.jobId,runId:X5($.jobId,$.runAtMs)});else if($.action==="finished")k({type:"cron_run_finished",jobId:$.jobId,runId:X5($.jobId,$.runAtMs),status:H8($.status),durationMs:$.durationMs??0,summary:$.summary,error:$.error});MZ(Z,{includeDisabled:!0})}function O8(Z){if(H0)return;H0=g3(Z,($)=>{K8(Z,$)})}function B8(){if(H0)H0(),H0=null}async function L8(Z){let{envelope:$,accountId:Q,config:X,core:Y,logger:H}=Z,V=X,J=R($.conversationId);X4({...$,conversationId:J});let q=Y.channel.routing.resolveAgentRoute({cfg:V,channel:"botmobile",accountId:Q,peer:{kind:"dm",id:J}}),K=D5(V,$.agentId);if($.agentId&&!K)H.info(`${u} ignoring invalid agent override "${$.agentId}" for conv=${J}`);if(K&&K!==q.agentId)q={...q,agentId:K,sessionKey:$5(q.sessionKey,K),mainSessionKey:$5(q.mainSessionKey,K)};M3({sessionKey:q.sessionKey,conversationId:J}),M3({sessionKey:q.mainSessionKey,conversationId:J});let B=SZ(V,q.agentId);F0(J,{id:q.agentId,name:B.name,emoji:B.emoji},$.timestamp);let O=$8(B.name,B.emoji);if(N3.get(J)!==O)N3.set(J,O),k({type:"conversation_list",conversations:[{id:J,name:O,createdAt:$.timestamp,lastActivity:$.timestamp}]});let D=[];if($.pendingAttachments&&LZ?.fileReceiver)for(let P of $.pendingAttachments){let f=LZ.fileReceiver.getFilePath(P.transferId);if(f)D.push({fileName:P.fileName,mimeType:P.mimeType,filePath:f});else H.error(`${u} attachment ${P.transferId} (${P.fileName}) not found on disk`)}let U=$.body;if(D.length>0){let P=D.map((f)=>`[Attached: ${f.fileName} — file://${f.filePath}]`);U=U?`${U}
1
+ import{createRequire as f3}from"node:module";var k3=Object.create;var{getPrototypeOf:A3,defineProperty:b0,getOwnPropertyNames:x3}=Object;var T3=Object.prototype.hasOwnProperty;var h3=(Z,$,X)=>{X=Z!=null?k3(A3(Z)):{};let Q=$||!Z||!Z.__esModule?b0(X,"default",{value:Z,enumerable:!0}):X;for(let Y of x3(Z))if(!T3.call(Q,Y))b0(Q,Y,{get:()=>Z[Y],enumerable:!0});return Q};var b3=(Z,$)=>{for(var X in $)b0(Z,X,{get:$[X],enumerable:!0,configurable:!0,set:(Q)=>$[X]=()=>Q})};var OZ=(Z,$)=>()=>(Z&&($=Z(Z=0)),$);var I3=f3(import.meta.url);function h1(Z){f0=Z}function J0(){if(!f0)throw Error("BotMobile runtime not initialized");return f0}var f0=null;import u3 from"node:fs";import I0 from"node:os";import oZ from"node:path";function bZ(Z){if(typeof Z!=="string")return;let $=Z.trim();return $.length>0?$:void 0}function nZ(Z){return(bZ(Z)??"main").toLowerCase()}function y0(Z){let $=Z.agents?.list;if(!Array.isArray($))return[];return $.filter((X)=>!!X&&typeof X==="object")}function m3(Z){let $=y0(Z);if($.length===0)return"main";let X=$.find((Q)=>Q.default===!0);return nZ((X??$[0])?.id)}function f1(Z){if(Z.startsWith("~"))return oZ.resolve(Z.replace(/^~/,I0.homedir()));return oZ.resolve(Z)}function g3(Z,$){let X=nZ($),Y=y0(Z).find((J)=>nZ(J.id)===X),H=bZ(Y?.workspace);if(H)return f1(H);let V=m3(Z);if(X===V){let J=bZ(Z.agents?.defaults?.workspace);if(J)return f1(J);return oZ.join(I0.homedir(),".openclaw","workspace")}return oZ.join(I0.homedir(),".openclaw",`workspace-${X}`)}function I1(Z,$){let X=Z.split(/\r?\n/);for(let Q=0;Q<X.length;Q++){let H=X[Q].replace(/\*\*/g,"").trim().match(new RegExp(`^(?:[-*]\\s*)?${$}\\s*:\\s*(.*?)\\s*$`,"i"));if(!H)continue;let V=H[1]?.trim();if(!V&&Q+1<X.length)V=X[Q+1].replace(/\*\*/g,"").trim();if(!V)continue;let J=V.replace(/^["'`]|["'`]$/g,"").trim();if(!J)continue;return J}return}function p3(Z){let $=Date.now(),X=b1.get(Z);if(X&&$-X.loadedAt<v3)return{name:X.name,emoji:X.emoji};let Q=oZ.join(Z,"IDENTITY.md"),Y,H;try{let V=u3.readFileSync(Q,"utf8");Y=I1(V,"name"),H=I1(V,"emoji")}catch{Y=void 0,H=void 0}return b1.set(Z,{loadedAt:$,name:Y,emoji:H}),{name:Y,emoji:H}}function fZ(Z,$){let X=nZ($),Y=y0(Z).find((K)=>nZ(K.id)===X),H=bZ(Y?.identity?.emoji),V=bZ(Y?.identity?.name),J=g3(Z,X),q=p3(J);if(V)return{name:V,emoji:H??q.emoji,source:"identity-config",emojiSource:H?"identity-config":q.emoji?"identity-file":void 0};let O=q.name;if(O)return{name:O,emoji:H??q.emoji,source:"identity-file",emojiSource:H?"identity-config":q.emoji?"identity-file":void 0};let B=bZ(Y?.name);if(B)return{name:B,emoji:H??q.emoji,source:"config-name",emojiSource:H?"identity-config":q.emoji?"identity-file":void 0};return{name:X||"Assistant",emoji:H??q.emoji,source:"agent-id",emojiSource:H?"identity-config":q.emoji?"identity-file":void 0}}var b1,v3=30000;var q0=OZ(()=>{b1=new Map});function R(Z){let $=Z.trim();if(!$)return Z;if(c3.test($))return $.toUpperCase();return $}var c3;var O0=OZ(()=>{c3=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i});import v1 from"node:fs";import aZ from"node:path";import y1 from"node:os";import{randomUUID as K0}from"node:crypto";import tZ from"ws";function g1(Z){let $=Z.cron?.store;if(typeof $==="string"&&$.trim()){let X=$.trim();if(X.startsWith("~"))return aZ.resolve(X.replace("~",y1.homedir()));return aZ.resolve(X)}return aZ.join(y1.homedir(),".openclaw","cron","jobs.json")}function i3(Z,$){return aZ.join(aZ.dirname(Z),"runs",`${$}.jsonl`)}function u0(Z){let $=Z.gateway?.port;if(typeof $==="number"&&Number.isFinite($)&&$>0)return $;return l3}function v0(Z){let $=Z.gateway?.auth?.token;return typeof $==="string"&&$.trim()?$.trim():void 0}function m0(Z){return typeof Z==="object"&&Z!==null}function r3(Z){if(!m0(Z))return!1;return Z.type==="res"&&typeof Z.id==="string"&&typeof Z.ok==="boolean"}function u1(Z){if(!m0(Z))return!1;return Z.type==="event"&&typeof Z.event==="string"}function s3(Z){if(!m0(Z))return null;let{jobId:$,action:X}=Z;if(typeof $!=="string"||!$.trim())return null;if(X!=="added"&&X!=="updated"&&X!=="removed"&&X!=="started"&&X!=="finished")return null;let Q={jobId:$,action:X};if(typeof Z.runAtMs==="number"&&Number.isFinite(Z.runAtMs))Q.runAtMs=Z.runAtMs;if(typeof Z.durationMs==="number"&&Number.isFinite(Z.durationMs))Q.durationMs=Z.durationMs;if(Z.status==="ok"||Z.status==="error"||Z.status==="skipped")Q.status=Z.status;if(typeof Z.error==="string")Q.error=Z.error;if(typeof Z.summary==="string")Q.summary=Z.summary;if(typeof Z.sessionId==="string")Q.sessionId=Z.sessionId;if(typeof Z.sessionKey==="string")Q.sessionKey=Z.sessionKey;if(typeof Z.nextRunAtMs==="number"&&Number.isFinite(Z.nextRunAtMs))Q.nextRunAtMs=Z.nextRunAtMs;return Q}class p1{cfg;tag;ws=null;reconnectTimer=null;reconnectDelayMs=1000;connectRequestId=null;stopped=!1;connected=!1;pending=new Map;cronListeners=new Set;constructor(Z,$){this.cfg=Z;this.tag=$}start(){this.stopped=!1,this.ensureConnected()}stop(){if(this.stopped=!0,this.connected=!1,this.connectRequestId=null,this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;let Z=this.ws;if(this.ws=null,Z)try{Z.close()}catch{}this.failPending("gateway bridge stopped")}isConnected(){return this.connected&&this.ws!==null&&this.ws.readyState===tZ.OPEN}listenerCount(){return this.cronListeners.size}addCronListener(Z){return this.cronListeners.add(Z),this.start(),()=>{this.cronListeners.delete(Z)}}async request(Z,$){let X=this.ws;if(!this.isConnected()||!X)return{ok:!1,error:"gateway bridge not connected"};let Q=K0(),H=JSON.stringify({type:"req",id:Q,method:Z,params:$});return await new Promise((V)=>{let J=setTimeout(()=>{this.pending.delete(Q),V({ok:!1,error:`gateway ${Z} timeout after ${B0}ms`})},B0);this.pending.set(Q,{resolve:V,timeout:J});try{X.send(H)}catch(q){this.pending.delete(Q),clearTimeout(J),V({ok:!1,error:`gateway WS send failed: ${String(q)}`})}})}ensureConnected(){if(this.stopped)return;if(this.ws&&this.ws.readyState===tZ.OPEN)return;if(this.ws&&this.ws.readyState===tZ.CONNECTING)return;if(this.reconnectTimer)return;let Z=u0(this.cfg),$=v0(this.cfg),X=`ws://127.0.0.1:${Z}`,Q=new tZ(X,{maxPayload:4194304});this.ws=Q,this.connected=!1;let Y=!1,H=()=>{if(Y)return;Y=!0,this.connectRequestId=K0();let V={minProtocol:3,maxProtocol:3,client:{id:"gateway-client",version:"dev",platform:process.platform,mode:"backend"},caps:[],role:"operator",scopes:["operator.admin"]};if($)V.auth={token:$};try{Q.send(JSON.stringify({type:"req",id:this.connectRequestId,method:"connect",params:V}))}catch(J){console.error(`${this.tag} bridge connect send failed: ${String(J)}`)}};Q.on("open",()=>{H()}),Q.on("message",(V)=>{try{let J=JSON.parse(String(V));if(r3(J)){if(J.id===this.connectRequestId){if(!J.ok){this.connected=!1,console.error(`${this.tag} bridge connect failed: ${J.error?.message??"unknown"}`);try{Q.close()}catch{}return}this.connected=!0,this.reconnectDelayMs=1000;return}let q=this.pending.get(J.id);if(q)if(this.pending.delete(J.id),clearTimeout(q.timeout),J.ok)q.resolve({ok:!0,payload:J.payload});else q.resolve({ok:!1,error:J.error?.message??"unknown error"});return}if(u1(J)&&J.event==="cron"){let q=s3(J.payload);if(!q)return;for(let O of this.cronListeners)try{O(q)}catch(B){console.error(`${this.tag} cron listener failed: ${String(B)}`)}return}if(u1(J)&&J.event==="connect.challenge"){if(!Y)H()}}catch{}}),Q.on("error",(V)=>{console.error(`${this.tag} bridge WS error: ${String(V)}`)}),Q.on("close",()=>{if(this.ws===Q)this.ws=null;this.connected=!1,this.connectRequestId=null,this.failPending("gateway connection closed"),this.scheduleReconnect()})}scheduleReconnect(){if(this.stopped)return;if(this.reconnectTimer)return;if(this.cronListeners.size===0)return;let Z=this.reconnectDelayMs;this.reconnectDelayMs=Math.min(this.reconnectDelayMs*2,d3),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.ensureConnected()},Z)}failPending(Z){for(let[$,X]of this.pending)this.pending.delete($),clearTimeout(X.timeout),X.resolve({ok:!1,error:Z})}}function c1(Z){return`${u0(Z)}|${v0(Z)??""}`}function o3(Z){let $=c1(Z);if(t&&L0===$)return t;if(t)t.stop();return t=new p1(Z,m1),L0=$,t}function l1(Z,$){let Q=o3(Z).addCronListener($);return()=>{if(Q(),t&&t.listenerCount()===0)t.stop(),t=null,L0=null}}async function g0(Z,$,X){let Q=c1(Z);if(t&&L0===Q&&t.isConnected()){let Y=await t.request($,X);if(Y.ok||Y.error!=="gateway bridge not connected")return Y}return await n3(Z,$,X)}async function n3(Z,$,X){let Q=u0(Z),Y=v0(Z),H=`ws://127.0.0.1:${Q}`;return new Promise((V)=>{let J=!1,q=(N)=>{if(J)return;J=!0,clearTimeout(O);try{B.close()}catch{}V(N)},O=setTimeout(()=>{q({ok:!1,error:`gateway RPC timeout after ${B0}ms`})},B0),B=new tZ(H,{maxPayload:4194304}),K=null,L=null,D=!1,U=null,_=(N)=>{if(D)return;if(D=!0,U)clearTimeout(U),U=null;K=K0();let W={minProtocol:3,maxProtocol:3,client:{id:"gateway-client",version:"dev",platform:process.platform,mode:"backend"},caps:[],role:"operator",scopes:["operator.admin"]};if(Y)W.auth={token:Y};B.send(JSON.stringify({type:"req",id:K,method:"connect",params:W}))};B.on("open",()=>{U=setTimeout(()=>_(),750)}),B.on("message",(N)=>{try{let W=JSON.parse(String(N));if(W.type==="event"){if(W.event==="connect.challenge"){let h=W.payload?.nonce;_(typeof h==="string"?h:void 0)}return}if(W.type==="res"&&W.id===K){if(!W.ok){q({ok:!1,error:`gateway connect failed: ${W.error?.message??"unknown"}`});return}L=K0(),B.send(JSON.stringify({type:"req",id:L,method:$,params:X}));return}if(W.type==="res"&&W.id===L){if(W.ok)q({ok:!0,payload:W.payload});else q({ok:!1,error:W.error?.message??"unknown error"});return}}catch{}}),B.on("error",(N)=>{q({ok:!1,error:`gateway WS error: ${String(N)}`})}),B.on("close",()=>{q({ok:!1,error:"gateway WS closed unexpectedly"})})})}function p0(Z){let $=g1(Z);try{let X=v1.readFileSync($,"utf-8");return JSON.parse(X)?.jobs??[]}catch(X){return console.error(`${m1} failed to read cron store at ${$}: ${String(X)}`),[]}}function d1(Z,$,X=20){let Q=g1(Z),Y=i3(Q,$);try{let H=v1.readFileSync(Y,"utf-8");if(!H.trim())return[];let V=H.split(`
2
+ `),J=[];for(let q=V.length-1;q>=0&&J.length<X;q--){let O=V[q]?.trim();if(!O)continue;try{let B=JSON.parse(O);if(B?.action==="finished"&&typeof B.ts==="number")J.push({ts:B.ts,jobId:B.jobId??$,action:B.action,status:B.status,error:B.error,summary:B.summary,durationMs:B.durationMs})}catch{}}return J}catch{return[]}}async function i1(Z,$){let X=await g0(Z,"cron.run",{id:$,mode:"force"});if(!X.ok)return{ok:!1,error:X.error};return{ok:!0}}async function r1(Z,$,X){let Q=await g0(Z,"cron.update",{id:$,patch:{enabled:X}});if(!Q.ok)return{ok:!1,error:Q.error};return{ok:!0}}async function s1(Z,$){let X=await g0(Z,"cron.add",$);if(!X.ok)return{ok:!1,error:X.error};return{ok:!0}}var m1="[botmobile:cron]",l3=18789,B0=15000,d3=30000,t=null,L0=null;var o1=()=>{};function T(Z){for(let $ of a3)try{$(Z)}catch{}}function M(){return Date.now()}function I(Z,$=M()){if(typeof Z==="number"&&Number.isFinite(Z)&&Z>0)return Math.floor(Z);return Math.floor($)}function n1(Z){if(!Z)return;let $=Z.trim();if(!$)return;if($.startsWith("conversation:"))return;if($.toLowerCase()==="conversation")return;return R($)}function d0(Z){if(!Z)return;let $=Z.trim().toLowerCase();return $.length>0?$:void 0}function U0(Z){let $=Z.trim();if(!$.toLowerCase().startsWith("cron:"))return;return d0($.slice(5))}function e3(Z,$){if(Z?.trim().toLowerCase()==="cron")return"cron";return U0($)?"cron":void 0}function EZ(Z){if(!Z)return;let $=Z.trim();return $.length>0?$:void 0}function c0(Z){return Z.id.startsWith("conversation:")&&Z.messageOrder.length===0}function Z2(Z){let $=I(Z,M());return KZ=Math.max(KZ+1,$),KZ}function zZ(Z){let $=++NZ;return Z2(Z),$}function i0(Z){if(!Z)return;return{...Z,skills:Z.skills?[...Z.skills]:void 0,skillDetails:Z.skillDetails?Z.skillDetails.map(($)=>({...$})):void 0,toolsAllow:Z.toolsAllow?[...Z.toolsAllow]:void 0,toolsDeny:Z.toolsDeny?[...Z.toolsDeny]:void 0}}function Z4(Z){return{...Z,details:i0(Z.details),usage:{...Z.usage}}}function $4(Z){return{...Z,schedule:Z.schedule?{...Z.schedule}:void 0}}function r0(Z){return{...Z}}function X4(Z){return{...Z}}function Q4(Z){return{id:`conversation:${Z}`,name:e1}}function l0(Z){let $=typeof Z.id==="string"?Z.id.trim().toLowerCase():"",X=typeof Z.name==="string"?Z.name.trim().toLowerCase():"";if(!$)return!0;if($==="conversation"||$.startsWith("conversation:"))return!0;if(!X)return!0;return X===e1.toLowerCase()||X==="conversation"}function $2(Z){return{isAgentActive:!1,isComposing:!1,lastUpdated:Z}}function Y4(Z,$){let X=r.get(Z);if(!X)return null;r.delete(Z),X.id=$;for(let Q of X.messages.values())Q.conversationId=$;r.set($,X);for(let[Q,Y]of YZ)if(Y===Z)YZ.set(Q,$);return X}function H4(Z){for(let $ of r.keys())if(R($)===Z)return $;return null}function a(Z,$){let X=R(Z),Q=r.get(X);if(Q)return Q;let Y=H4(X);if(Y&&Y!==X){let q=Y4(Y,X);if(q)return q}let H=I($,M()),V=U0(X),J={id:X,kind:V?"cron":void 0,cronJobId:V,cronName:void 0,cronAgentId:void 0,cronAgentName:void 0,cronAgentEmoji:void 0,agent:Q4(X),createdAt:H,updatedAt:H,revision:0,lastMessageRevision:0,activity:$2(H),messages:new Map,messageOrder:[]};return J.revision=zZ(H),r.set(X,J),J}function BZ(Z,$){let X=I($,M());Z.updatedAt=Math.max(Z.updatedAt,X)}function HZ(Z,$,X){let Q=zZ($);if(Z.revision=Math.max(Z.revision,Q),X?.messageChanged)Z.lastMessageRevision=Math.max(Z.lastMessageRevision,Q);return Q}function V4(Z){for(let $ of Z.messages.values())if($.isStreaming)return!0;return!1}function QZ(Z,$,X){let Q=I(X,M()),Y=Z.activity,H=Y.activeAgentId,V=Object.prototype.hasOwnProperty.call($,"activeAgentId"),J=Object.prototype.hasOwnProperty.call($,"activeTool"),q={isAgentActive:$.isAgentActive??Y.isAgentActive,isComposing:$.isComposing??Y.isComposing,activeAgentId:V?$.activeAgentId:Y.activeAgentId,activeTool:J?$.activeTool:Y.activeTool,lastUpdated:Math.max(Y.lastUpdated,Q)};if(!q.isAgentActive&&!q.isComposing)q.activeAgentId=void 0,q.activeTool=void 0;else if(!q.isAgentActive)q.activeTool=void 0;if(!(q.isAgentActive!==Y.isAgentActive||q.isComposing!==Y.isComposing||q.activeAgentId!==Y.activeAgentId||q.activeTool!==Y.activeTool)){if(q.lastUpdated>Y.lastUpdated)Y.lastUpdated=q.lastUpdated;if(q.isAgentActive&&q.activeAgentId)YZ.set(q.activeAgentId,Z.id);return!1}if(Z.activity=q,H&&YZ.get(H)===Z.id&&q.activeAgentId!==H)YZ.delete(H);if(q.isAgentActive&&q.activeAgentId)YZ.set(q.activeAgentId,Z.id);return BZ(Z,Q),HZ(Z,Q),!0}function eZ(Z,$,X){let Q=I($,M()),Y=X?R(X):void 0,H=!1,V=YZ.get(Z);if(V&&V!==Y){let J=r.get(V);if(J)H=QZ(J,{isAgentActive:!1,isComposing:!1,activeAgentId:void 0,activeTool:void 0},Q)||H}for(let[J,q]of r){if(J===V)continue;if(J===Y)continue;if(q.activity.activeAgentId!==Z)continue;H=QZ(q,{isAgentActive:!1,isComposing:!1,activeAgentId:void 0,activeTool:void 0},Q)||H}if(Y)YZ.set(Z,Y);else YZ.delete(Z);return H}function J4(Z){while(Z.messageOrder.length>t3){let $=Z.messageOrder.shift();if(!$)break;Z.messages.delete($)}}function IZ(Z,$,X){let Q=I($.timestamp,M()),Y=Z.messages.get($.id);if(!Y){let V=HZ(Z,Q,{messageChanged:!0});Z.messages.set($.id,r0({...$,timestamp:Q,revision:V})),Z.messageOrder.push($.id),J4(Z),BZ(Z,Q);return}if(X==="append")Y.content+=$.content,Y.timestamp=Q,Y.isStreaming=$.isStreaming??Y.isStreaming;else Y.content=$.content,Y.role=$.role,Y.timestamp=Q,Y.isStreaming=$.isStreaming;let H=HZ(Z,Y.timestamp,{messageChanged:!0});Y.revision=H,BZ(Z,Y.timestamp)}function q4(Z){let $=[];for(let X of Z.messageOrder){let Q=Z.messages.get(X);if(!Q)continue;$.push(r0(Q))}return $.sort((X,Q)=>{if(X.timestamp===Q.timestamp)return X.id.localeCompare(Q.id);return X.timestamp-Q.timestamp}),$}function D0(Z,$){let X=$?.sinceTimestampMs,Q=typeof $?.lastMessageRevision==="number"&&Number.isFinite($.lastMessageRevision)?Math.max(0,Math.floor($.lastMessageRevision)):0,Y=q4(Z).filter((H)=>{if(Q>0){let V=typeof H.revision==="number"&&Number.isFinite(H.revision)?Math.max(0,Math.floor(H.revision)):0;if(V>Q)return!0;if(V>0)return!1}if(!X||!Number.isFinite(X)||X<=0)return!0;return H.timestamp>X});return{id:Z.id,kind:Z.kind,cronJobId:Z.cronJobId,cronName:Z.cronName,cronAgentId:Z.cronAgentId,cronAgentName:Z.cronAgentName,cronAgentEmoji:Z.cronAgentEmoji,agent:{...Z.agent},createdAt:Z.createdAt,updatedAt:Z.updatedAt,revision:Z.revision,lastMessageRevision:Z.lastMessageRevision,activity:X4(Z.activity),messages:Y}}function X2(Z){let $=Number.isFinite(Z.sessionTokensIn)?Z.sessionTokensIn:0,X=Number.isFinite(Z.sessionTokensOut)?Z.sessionTokensOut:0,Q=I(Z.lastActivityAt,M()),Y=Z.status==="working";return{id:Z.agentId,name:Z.name||Z.agentId,emoji:Z.emoji,color:Z.color,details:i0(Z.details),queue:Y?1:0,lastUpdated:Q,usage:{mode:"tokens",value:Math.max(0,$+X)},isRunning:Y,currentTask:Z.activeTool}}function Q2(Z,$){let X=I($??Z.lastRunAt??Z.nextRunAt,M());return{id:Z.id,name:Z.name,enabled:Z.enabled,isRunning:Z.isRunning,lastUpdated:X,agentId:Z.agentId,agentName:Z.agentName,agentEmoji:Z.agentEmoji,schedule:Z.schedule?{...Z.schedule}:void 0,nextRunAt:Z.nextRunAt,lastRunAt:Z.lastRunAt,lastRunStatus:Z.lastRunStatus,lastRunSummary:Z.lastRunSummary}}function Z0(Z){if(wZ.size>0)return[...wZ.values()].map(Z4);if(!Z||Z.length===0)return[];return Z.map(($)=>X2($))}function $0(Z){if(GZ.size>0)return[...GZ.values()].map($4);if(!Z||Z.length===0)return[];return Z.map(($)=>Q2($))}function t1(Z){let $=[...r.values()].filter((Y)=>!c0(Y)).sort((Y,H)=>H.updatedAt-Y.updatedAt).map((Y)=>D0(Y)),X=Z0(Z?.fallbackAgents),Q=$0(Z?.fallbackCronJobs);return{timestamp:KZ,stateBornAt:WZ,globalRevision:NZ,conversations:$,agents:X,cronJobs:Q}}function Y2(){r.clear(),wZ.clear(),GZ.clear(),YZ.clear(),WZ=M(),KZ=WZ,NZ=0}function H2(Z){let $=0;for(let X of Z){let Q=R(X.id),Y=U0(Q),H=e3(X.kind,Q),V=d0(X.cronJobId)??Y,J=EZ(X.cronName),q=EZ(X.cronAgentId),O=EZ(X.cronAgentName),B=EZ(X.cronAgentEmoji),K=new Map,L=[],D=0;for(let W of X.messages){let h=I(W.timestamp,M()),A=zZ(h);K.set(W.id,r0({...W,conversationId:Q,timestamp:h,revision:A})),L.push(W.id),$=Math.max($,h),D=A}let U=I(X.createdAt,M()),_=I(X.updatedAt,U),N=D>0?D:zZ(_);r.set(Q,{id:Q,kind:H,cronJobId:V,cronName:J,cronAgentId:q,cronAgentName:O,cronAgentEmoji:B,agent:{...X.agent},createdAt:U,updatedAt:_,revision:N,lastMessageRevision:D,activity:$2(_),messages:K,messageOrder:L}),$=Math.max($,_)}if($>0)Z2($)}function F0(Z,$,X){let Q=R(Z),Y=I(X,M()),H=a(Q,Y);H.agent={id:$.id||H.agent.id,name:$.name||H.agent.name,emoji:$.emoji??H.agent.emoji},BZ(H,Y),HZ(H,Y),T("conversations")}function s0(Z,$){let X=R(Z.conversationId),Q=I($,M()),Y=a(X,Q),H=U0(X),V=d0(Z.cronJobId)??H,J=Y.kind??(V?"cron":void 0),q=EZ(Z.cronName)??Y.cronName,O=EZ(Z.cronAgentId)??Y.cronAgentId,B=EZ(Z.cronAgentName)??Y.cronAgentName,K=EZ(Z.cronAgentEmoji)??Y.cronAgentEmoji,L={...Y.agent};if(Y.kind==="cron"||J==="cron"){if(q&&l0(Y.agent))L.name=q;if(K&&!L.emoji)L.emoji=K}if(!(Y.kind!==J||Y.cronJobId!==V||Y.cronName!==q||Y.cronAgentId!==O||Y.cronAgentName!==B||Y.cronAgentEmoji!==K||Y.agent.id!==L.id||Y.agent.name!==L.name||Y.agent.emoji!==L.emoji))return;Y.kind=J,Y.cronJobId=V,Y.cronName=q,Y.cronAgentId=O,Y.cronAgentName=B,Y.cronAgentEmoji=K,Y.agent=L,BZ(Y,Q),HZ(Y,Q),T("conversations")}function V2(Z){if(Z.from!=="user")return;let $=R(Z.conversationId),X=I(Z.timestamp,M()),Q=a($,X);IZ(Q,{id:Z.id,conversationId:$,role:"user",content:Z.body,timestamp:X,isStreaming:!1},"replace"),T("conversations")}function J2(Z){switch(Z.type){case"conversation_list":{for(let $ of Z.conversations){let X=R($.id),Q=I($.lastActivity,M()),Y=a(X,$.createdAt);Y.createdAt=Math.min(Y.createdAt,I($.createdAt,Y.createdAt)),Y.updatedAt=Math.max(Y.updatedAt,Q);let H=$.name.trim();if(H.length>0)Y.agent={id:Y.agent.id,name:H,emoji:Y.agent.emoji};HZ(Y,Q)}T("conversations");return}case"message":{let $=R(Z.conversationId),X=I(Z.timestamp,M()),Q=a($,X);if(IZ(Q,{id:Z.id,conversationId:$,role:Z.from==="user"?"user":"bot",content:Z.body,timestamp:X,isStreaming:!1},"replace"),Z.from==="bot")QZ(Q,{isComposing:!1,activeTool:void 0},X);T("conversations");return}case"stream_start":{let $=R(Z.conversationId),X=M(),Q=a($,X),Y=Q.agent.id.startsWith("conversation:")?void 0:Q.agent.id;QZ(Q,{isAgentActive:!0,isComposing:!0,activeAgentId:Y},X);let H=Q.messages.get(Z.messageId);if(H)H.isStreaming=!0,H.timestamp=X,H.role="bot",H.revision=HZ(Q,X,{messageChanged:!0}),BZ(Q,X);else IZ(Q,{id:Z.messageId,conversationId:$,role:"bot",content:"",timestamp:X,isStreaming:!0},"replace");T("conversations");return}case"stream_token":{let $=R(Z.conversationId),X=M(),Q=a($,X),Y=Q.agent.id.startsWith("conversation:")?void 0:Q.agent.id;QZ(Q,{isAgentActive:!0,isComposing:!0,activeAgentId:Y},X),IZ(Q,{id:Z.messageId,conversationId:$,role:"bot",content:Z.token,timestamp:X,isStreaming:!0},"append"),T("conversations");return}case"stream_end":{let $=R(Z.conversationId),X=M(),Q=a($,X);QZ(Q,{isAgentActive:!1,isComposing:!1,activeTool:void 0},X);let Y=Q.messages.get(Z.messageId);if(Y){if(Z.body.trim().length>0)Y.content=Z.body;Y.isStreaming=!1,Y.timestamp=X,Y.revision=HZ(Q,X,{messageChanged:!0}),BZ(Q,X)}else IZ(Q,{id:Z.messageId,conversationId:$,role:"bot",content:Z.body,timestamp:X,isStreaming:!1},"replace");T("conversations");return}case"composing":{if(Z.from!=="bot")return;let $=R(Z.conversationId),X=M(),Q=a($,X),Y=Q.agent.id.startsWith("conversation:")?void 0:Q.agent.id;QZ(Q,{isAgentActive:!0,isComposing:!0,activeAgentId:Y},X),T("conversations");return}case"tool_status":{let $=R(Z.conversationId),X=M(),Q=a($,X);if(Z.status==="running"){let Y=Q.agent.id.startsWith("conversation:")?void 0:Q.agent.id;QZ(Q,{isAgentActive:!0,isComposing:!1,activeAgentId:Y,activeTool:Z.tool},X)}else QZ(Q,{isAgentActive:V4(Q),isComposing:!1,activeTool:void 0},X);T("conversations");return}case"agent_list":{let $=!1,X=new Set;wZ.clear();for(let Y of Z.agents){X.add(Y.agentId),wZ.set(Y.agentId,X2(Y));let H=I(Y.lastActivityAt,M()),V=n1(Y.activeConversationId);if(Y.status==="working"&&V){$=eZ(Y.agentId,H,V)||$;let J=a(V,H);J.agent={id:Y.agentId||J.agent.id,name:Y.name||J.agent.name,emoji:Y.emoji??J.agent.emoji},$=QZ(J,{isAgentActive:!0,isComposing:J.activity.isComposing,activeAgentId:Y.agentId,activeTool:Y.activeTool},H)||$}else $=eZ(Y.agentId,H)||$}let Q=M();for(let Y of Array.from(YZ.keys())){if(X.has(Y))continue;$=eZ(Y,Q)||$}if(zZ(M()),T("agents"),$)T("conversations");return}case"agent_status":{let $=M(),X=wZ.get(Z.agentId)??{id:Z.agentId,name:Z.agentId,queue:0,lastUpdated:$,usage:{mode:"tokens",value:0},isRunning:Z.status==="working"},Q={...X,color:Z.color??X.color,details:Z.details?i0(Z.details):X.details,queue:Z.status==="working"?1:0,lastUpdated:I(Z.lastActivityAt,$),usage:{mode:"tokens",value:typeof Z.sessionTokensIn==="number"||typeof Z.sessionTokensOut==="number"?Math.max(0,(Z.sessionTokensIn??0)+(Z.sessionTokensOut??0)):X.usage.value},isRunning:Z.status==="working",currentTask:Z.activeTool};wZ.set(Z.agentId,Q);let Y=!1,H=Z.status==="working"?n1(Z.activeConversationId):void 0;if(H){Y=eZ(Z.agentId,Q.lastUpdated,H)||Y;let V=a(H,Q.lastUpdated);V.agent={id:Z.agentId||V.agent.id,name:Q.name||V.agent.name,emoji:Q.emoji??V.agent.emoji},Y=QZ(V,{isAgentActive:!0,isComposing:V.activity.isComposing,activeAgentId:Z.agentId,activeTool:Z.activeTool},Q.lastUpdated)||Y}else Y=eZ(Z.agentId,Q.lastUpdated)||Y;if(zZ(Q.lastUpdated),T("agents"),Y)T("conversations");return}case"cron_list":{GZ.clear();let $=M();for(let X of Z.jobs)GZ.set(X.id,Q2(X,$));zZ($),T("cronJobs");return}case"cron_run_started":{let $=M(),X=GZ.get(Z.jobId)??{id:Z.jobId,name:Z.jobId,enabled:!0,isRunning:!1,lastUpdated:$};GZ.set(Z.jobId,{...X,isRunning:!0,lastUpdated:$}),zZ($),T("cronJobs");return}case"cron_run_finished":{let $=M(),X=GZ.get(Z.jobId)??{id:Z.jobId,name:Z.jobId,enabled:!0,isRunning:!1,lastUpdated:$};GZ.set(Z.jobId,{...X,isRunning:!1,lastRunAt:$,lastRunStatus:Z.status,lastRunSummary:Z.summary,lastUpdated:$}),zZ($),T("cronJobs");return}default:return}}function a1(Z){return Z.startsWith("t:")}function q2(Z){let $=R(Z.conversationId),{role:X,content:Q,timestamp:Y,stableId:H}=Z,V=I(Y,M()),J=a($,V),q=a1(H),O=!1;if(Z.agent){let L=l0(J.agent),D=l0(Z.agent),U=typeof Z.agent.id==="string"&&Z.agent.id.trim().length>0&&Z.agent.id===J.agent.id;if(L||U||!D&&!J.agent.emoji&&!!Z.agent.emoji){let _={id:Z.agent.id||J.agent.id,name:Z.agent.name||J.agent.name,emoji:Z.agent.emoji??J.agent.emoji};if(O=_.id!==J.agent.id||_.name!==J.agent.name||_.emoji!==J.agent.emoji,O)J.agent=_,BZ(J,V),HZ(J,V)}}if(J.messages.has(H)){if(O)T("conversations");return!1}let B=J.messageOrder,K=Math.max(0,B.length-K4);for(let L=B.length-1;L>=K;L--){let D=J.messages.get(B[L]);if(!D)continue;if(D.role!==X)continue;let U=D.content===Q||Q.startsWith(D.content)||D.content.startsWith(Q);if(X==="bot"&&q&&!a1(D.id)&&V<=D.timestamp&&U){if(!D.isStreaming&&Q.length>D.content.length)D.content=Q,D.timestamp=Math.max(D.timestamp,V),D.revision=HZ(J,D.timestamp,{messageChanged:!0}),BZ(J,D.timestamp),T("conversations");else if(O)T("conversations");return!1}if(Math.abs(D.timestamp-V)>O4)continue;if(U){if(!D.isStreaming&&Q.length>D.content.length)D.content=Q,D.timestamp=V,D.revision=HZ(J,V,{messageChanged:!0}),BZ(J,V),T("conversations");else if(O)T("conversations");return!1}}return IZ(J,{id:H,conversationId:$,role:X,content:Q,timestamp:V,isStreaming:!1},"replace"),T("conversations"),!0}function o0(Z){let $=R(Z),X=r.get($);if(!X)return null;return D0(X)}function B4(Z){let $=new Map;if(!Array.isArray(Z))return $;for(let X of Z){if(!X||typeof X.id!=="string"||X.id.length===0)continue;let Q=R(X.id),Y=typeof X.conversationRevision==="number"&&Number.isFinite(X.conversationRevision)?Math.max(0,Math.floor(X.conversationRevision)):0,H=typeof X.lastMessageRevision==="number"&&Number.isFinite(X.lastMessageRevision)?Math.max(0,Math.floor(X.lastMessageRevision)):0,V=typeof X.lastMessageTs==="number"&&Number.isFinite(X.lastMessageTs)?Math.max(0,Math.floor(X.lastMessageTs)):0;$.set(Q,{conversationRevision:Y,lastMessageRevision:H,lastMessageTs:V})}return $}function n0(Z){let $=I(Z.stateBornAt,0),X=typeof Z.globalRevision==="number"&&Number.isFinite(Z.globalRevision)?Math.max(0,Math.floor(Z.globalRevision)):0,Q=B4(Z.conversations);if(X>0||$>0||Q.size>0){if($>0&&$!==WZ)return{mode:"snapshot",state:t1(Z)};if(X>=NZ)return{mode:"delta",state:{timestamp:KZ,stateBornAt:WZ,globalRevision:NZ,conversations:[],agents:Z0(Z.fallbackAgents),cronJobs:$0(Z.fallbackCronJobs)}};let O=[...r.values()].filter((B)=>!c0(B)).sort((B,K)=>K.updatedAt-B.updatedAt).map((B)=>{let K=Q.get(B.id),L=K?.conversationRevision??0,D=K?.lastMessageRevision??0,U=K?.lastMessageTs??0;if(L>0||D>0){if(B.revision<=L&&B.lastMessageRevision<=D&&B.updatedAt<=U)return null}else if(U>0&&B.updatedAt<=U)return null;return D0(B,{lastMessageRevision:D,sinceTimestampMs:U>0?U:void 0})}).filter((B)=>B!==null);return{mode:"delta",state:{timestamp:KZ,stateBornAt:WZ,globalRevision:NZ,conversations:O,agents:Z0(Z.fallbackAgents),cronJobs:$0(Z.fallbackCronJobs)}}}let H=I(Z.sinceTimestampMs,0);if(!H||H<WZ)return{mode:"snapshot",state:t1(Z)};if(H>=KZ)return{mode:"delta",state:{timestamp:KZ,stateBornAt:WZ,globalRevision:NZ,conversations:[],agents:Z0(Z.fallbackAgents),cronJobs:$0(Z.fallbackCronJobs)}};let V=[...r.values()].filter((O)=>!c0(O)).filter((O)=>O.updatedAt>H).sort((O,B)=>B.updatedAt-O.updatedAt).map((O)=>{let K=Q.get(O.id)?.lastMessageRevision??0;return D0(O,{sinceTimestampMs:H,lastMessageRevision:K})}),J=Z0(Z.fallbackAgents),q=$0(Z.fallbackCronJobs);return{mode:"delta",state:{timestamp:KZ,stateBornAt:WZ,globalRevision:NZ,conversations:V,agents:J,cronJobs:q}}}var e1="Assistant",t3=1500,r,wZ,GZ,YZ,WZ,KZ,NZ=0,a3,O4=2000,K4=20;var X0=OZ(()=>{O0();r=new Map,wZ=new Map,GZ=new Map,YZ=new Map,WZ=Date.now(),KZ=Date.now(),a3=new Set});import ZZ from"node:fs";import B2 from"node:os";import yZ from"node:path";function s(Z){if(typeof Z!=="string")return null;let $=Z.trim();return $.length>0?$:null}function S4(Z){if(typeof Z==="number"&&Number.isFinite(Z))return Math.max(0,Math.floor(Z));if(typeof Z==="string"){let $=Number(Z);if(Number.isFinite($))return Math.max(0,Math.floor($))}return 0}function G0(Z){let $=Z.trim().toLowerCase();return $==="botmobile:bot:default"||$.startsWith("botmobile:bot:")}function U2(Z){if(!Z)return!0;let $=Z.trim().toLowerCase();if(!$)return!0;return $==="conversation"||$.startsWith("conversation:")}function w4(Z){let $=Array.isArray(Z.bindings)?Z.bindings:[];for(let H of $){if(!H||typeof H!=="object")continue;let V=s(H.agentId);if(!V)continue;let J=H.match,q=s(J?.channel)?.toLowerCase(),O=s(J?.accountId)?.toLowerCase();if(q!=="botmobile")continue;if(O&&O!=="default")continue;return V}let X=Array.isArray(Z.agents?.list)?Z.agents.list:[],Q=X.find((H)=>H?.default===!0);return s(Q?.id)??s(X[0]?.id)??"assistant"}function j4(Z){let $=Z.match(F4);if(!$)return null;let X=R($[2]);if(G0(X))return null;return{agentId:$[1],conversationId:X}}function e0(Z){return Z.trim().toLowerCase()}function C4(Z){return`cron:${e0(Z)}`}function F2(Z){if(!Z.toLowerCase().startsWith("cron:"))return null;let $=Z.slice(5).trim();return $.length>0?e0($):null}function k4(Z){let $=Z.match(G4);if(!$)return null;let X=$[1].trim(),Q=e0($[2]);if(!X||!Q)return null;return{agentId:X,jobId:Q}}function A4(Z){let $=s(Z);if(!$)return null;let X=$.replace(/^cron:\s*/i,"").trim();return X.length>0?X:null}function x4(Z,$){let X=s(Z.sessionFile);if(X)return X;let Q=s(Z.sessionId);if(!Q)return null;let Y=yZ.join(B2.homedir(),".openclaw","agents",$,"sessions",`${Q}.jsonl`);try{if(ZZ.existsSync(Y))return Y}catch{}return null}function G2(Z){return`Task ${Z.slice(0,8).toUpperCase()}`}function a0(Z,$,X){if(X?.resolveAgentDisplay)return X.resolveAgentDisplay({cfg:Z,agentId:$});let Q=fZ(Z,$);return{name:Q.name,emoji:Q.emoji}}function W2(Z,$){if(!Z||!$?.resolveCronSnapshot)return null;return $.resolveCronSnapshot(Z)??null}function T4(Z){if(D2.test(Z))return null;let $=Z.match(W4);if(!$)return null;let X=$[1].trim();if(!X)return null;if(U2(X))return null;return X}function h4(Z){let $=Z.match(D2);if(!$)return null;let X=R($[1]);if(G0(X))return null;return X}function b4(Z){if(!Z||typeof Z!=="object")return null;let $=s(Z.provider)?.toLowerCase(),X=s(Z.surface)?.toLowerCase(),Q=s(Z.chatType)?.toLowerCase(),Y=s(Z.label),H=s(Z.from);if(!($==="botmobile"||X==="botmobile"||H!==null&&K2.test(H)))return null;if(Q&&Q!=="direct")return null;if(Y){let J=R(Y);if(!G0(J))return J}if(H){let J=H.match(K2);if(J&&J[1].trim().length>0){let q=R(J[1]);if(!G0(q))return q}}return null}function f4(Z,$,X){let Q=S4($.updatedAt),Y=k4(Z);if(Y){let K=x4($,Y.agentId);if(!K)return null;return{conversationId:C4(Y.jobId),agentId:Y.agentId,sessionFile:K,updatedAt:Q,kind:"cron",cronJobId:Y.jobId,cronLabel:A4($.label)??void 0}}let H=s($.sessionFile);if(!H)return null;let V=j4(Z);if(V)return{conversationId:V.conversationId,agentId:V.agentId,sessionFile:H,updatedAt:Q};let J=b4($.origin);if(!J)return null;let O=h4(Z)??J,B=T4(Z)??X;return{conversationId:O,agentId:B,sessionFile:H,updatedAt:Q}}function Z1(Z){let $=w4(Z),X=yZ.join(B2.homedir(),".openclaw"),Q=yZ.join(X,"agents"),Y;try{Y=ZZ.readdirSync(Q,{withFileTypes:!0}).filter((V)=>V.isDirectory()).map((V)=>V.name)}catch{return[]}let H=[];for(let V of Y){let J=yZ.join(Q,V,"sessions","sessions.json"),q;try{q=JSON.parse(ZZ.readFileSync(J,"utf8"))}catch{continue}for(let[O,B]of Object.entries(q)){let K=f4(O,B,$);if(!K)continue;H.push(K)}}return H.sort((V,J)=>J.updatedAt-V.updatedAt),H}function I4(Z,$,X){let Q=[],Y=0;if(X){let H=Z.indexOf(10);if(H===-1)return[];Y=H+1}for(let H=Y;H<Z.length;H++){if(Z[H]!==10)continue;let V=Z.subarray(Y,H),J=$+Y;if(Y=H+1,V.length===0)continue;let q=V.toString("utf8").trim();if(!q)continue;Q.push({line:q,offset:J})}if(Y<Z.length){let V=Z.subarray(Y).toString("utf8").trim();if(V)Q.push({line:V,offset:$+Y})}return Q}function z2(Z){if(!Array.isArray(Z))return"";let $=[];for(let X of Z)if(X&&typeof X==="object"&&X.type==="text"&&typeof X.text==="string")$.push(X.text);return $.join(`
3
+ `)}function _2(Z){try{return JSON.parse(Z)}catch{return null}}function N2(Z,$){if(typeof Z==="number"&&Number.isFinite(Z)&&Z>0)return Math.floor(Z);if(typeof Z==="string"&&Z.trim().length>0){let X=Number(Z);if(Number.isFinite(X)&&X>0)return Math.floor(X);let Q=Date.parse(Z);if(Number.isFinite(Q)&&Q>0)return Math.floor(Q)}if(typeof $==="number"&&Number.isFinite($)&&$>0)return Math.floor($);if(typeof $==="string"&&$.trim().length>0){let X=Number($);if(Number.isFinite(X)&&X>0)return Math.floor(X);let Q=Date.parse($);if(Number.isFinite(Q)&&Q>0)return Math.floor(Q)}return 0}function E2(Z){if(!R4.test(Z))return!1;let $=Z.match(M4);if(!$)return!1;let X=$[1];return X==="user"||X==="assistant"}function y4(Z){let $=Z.trim();if(!N4.test($))return $;let X=Array.from($.matchAll(_4));if(X.length===0)return $;let Q=X[X.length-1],Y=typeof Q.index==="number"?Q.index:0;return $.slice(Y).trim()}function P2(Z){let $=Z.match(P4),X=$?$[1].trim():void 0,Q=Z.replace(E4,"").trim();return{clean:y4(Q).replace(z4,"").trim(),messageId:X}}function u4(Z){let{sessionFile:$,limit:X}=Z,Q=R(Z.conversationId),Y=yZ.basename($),H=null;try{H=ZZ.openSync($,"r");let V=ZZ.fstatSync(H).size;if(V<=0)return[];let J=Math.min(L2,V);while(!0){let q=Math.max(0,V-J),O=V-q,B=Buffer.allocUnsafe(O);ZZ.readSync(H,B,0,O,q);let K=I4(B,q,q>0),L=[];for(let U=K.length-1;U>=0&&L.length<X;U--){let _=K[U];if(!E2(_.line))continue;let N=_2(_.line);if(!N||N.type!=="message"||!N.message)continue;let W=N.message;if(W.role!=="user"&&W.role!=="assistant")continue;let h=z2(W.content);if(!h.trim())continue;let A=W.role==="user"?"user":"bot",p=N2(W.timestamp,N.timestamp),b,w;if(A==="user"){let{clean:c,messageId:j}=P2(h);b=c,w=j?`u:${j}`:`t:${Y}:${_.offset}`}else b=h,w=`t:${Y}:${_.offset}`;if(!b.trim())continue;L.push({id:w,conversationId:Q,role:A,content:b,timestamp:p,isStreaming:!1})}let D=L.reverse();if(D.length>=X||q===0)return D;if(J>=O2)return D;J=Math.min(V,J*2,O2)}}catch{return[]}finally{if(H!==null)try{ZZ.closeSync(H)}catch{}}}function R2(Z,$,X,Q,Y){let H=yZ.basename(Z),V=R($.conversationId),J,q;try{J=ZZ.openSync(Z,"r"),q=ZZ.fstatSync(J).size}catch{return{messages:[],cursor:Q}}try{if(q<Q.offset)Q={offset:Math.max(0,q-L2)};if(q<=Q.offset)return{messages:[],cursor:Q};let O=Q.offset,B=q-O,K=Buffer.alloc(B);ZZ.readSync(J,K,0,B,O);let L=0;if(O>0){let j=Buffer.alloc(1);try{if(ZZ.readSync(J,j,0,1,O-1),j[0]!==10){let E=K.indexOf(10);if(E===-1)return{messages:[],cursor:{offset:O}};L=E+1}}catch{}}let D=K.subarray(L),U=O+L,_=D.toString("utf8");if(!_)return{messages:[],cursor:{offset:q}};let N=_.endsWith(`
4
+ `),W=_.split(`
5
+ `);if(N)W.pop();else W.pop();let h=$.cronJobId??F2(V),A=W2(h,Y),p=$.kind==="cron"?{id:$.cronAgentId??$.agentId,name:$.cronLabel??A?.name??(h?G2(h):"Scheduled Task"),emoji:$.cronAgentEmoji??A?.agentEmoji??"\uD83D\uDD52"}:(()=>{let j=a0(X,$.agentId,Y);return{id:$.agentId,name:j.name??$.agentId,emoji:j.emoji}})(),b=[],w=U;for(let j of W){let E=Buffer.byteLength(j,"utf8")+1;if(j.trim()){if(!E2(j)){w+=E;continue}let v=_2(j);if(v&&v.type==="message"&&v.message){let z=v.message;if(z.role==="user"||z.role==="assistant"){let m=z2(z.content);if(m.trim()){let x=z.role==="user"?"user":"bot",l=N2(z.timestamp,v.timestamp),n,XZ;if(x==="user"){let{clean:d,messageId:hZ}=P2(m);n=d,XZ=hZ?`u:${hZ}`:`t:${H}:${w}`}else n=m,XZ=`t:${H}:${w}`;if(n.trim())b.push({conversationId:V,agentId:$.agentId,agent:p,role:x,content:n,timestamp:l,stableId:XZ})}}}}w+=E}return{messages:b,cursor:{offset:N?q:w}}}finally{try{ZZ.closeSync(J)}catch{}}}function M2(Z,$){let X=Z1(Z),Q=new Map;for(let V of X){let J=Q.get(V.conversationId)??[];J.push(V),Q.set(V.conversationId,J)}let Y=[...Q.entries()].map(([V,J])=>{let q=[...J].sort((K,L)=>L.updatedAt-K.updatedAt),O=[],B=new Set;for(let K of q){if(B.has(K.sessionFile))continue;B.add(K.sessionFile),O.push(K)}return{conversationId:V,mappings:O,updatedAt:O[0]?.updatedAt??0}}).sort((V,J)=>J.updatedAt-V.updatedAt),H=[];for(let V=0;V<Y.length;V++){let J=Y[V],q=V<D4,O=J.mappings.slice(0,U4),B=new Map;if(q)for(let z of O){let m=u4({sessionFile:z.sessionFile,conversationId:J.conversationId,limit:t0});for(let x of m){let l=B.get(x.id);if(!l||x.timestamp>=l.timestamp)B.set(x.id,x)}}let K=[...B.values()].sort((z,m)=>{if(z.timestamp===m.timestamp)return z.id.localeCompare(m.id);return z.timestamp-m.timestamp}),L=K.length>t0?K.slice(K.length-t0):K,D=L.map((z)=>z.timestamp).filter((z)=>z>0),U=J.mappings.map((z)=>z.updatedAt).filter((z)=>z>0),_=U.length>0?Math.min(...U):J.updatedAt,N=U.length>0?Math.max(...U):J.updatedAt,W=D.length>0?Math.min(...D):_,h=D.length>0?Math.max(N,...D):N,A=J.mappings.find((z)=>!U2(z.agentId))??J.mappings[0],p=A.cronJobId??F2(J.conversationId),b=W2(p,$),w=J.conversationId.toLowerCase().startsWith("cron:"),c=w?A.cronAgentId??b?.agentId??A.agentId:void 0,j=c?a0(Z,c,$):void 0,E=w?A.cronLabel??b?.name??(p?G2(p):"Scheduled Task"):void 0,v=w?{id:c??A.agentId,name:E??"Scheduled Task",emoji:A.cronAgentEmoji??b?.agentEmoji??"\uD83D\uDD52"}:(()=>{let z=a0(Z,A.agentId,$);return{id:A.agentId,name:z.name??A.agentId,emoji:z.emoji}})();H.push({id:J.conversationId,agent:v,createdAt:W,updatedAt:h,kind:w?"cron":void 0,cronJobId:w?p??void 0:void 0,cronName:w?E:void 0,cronAgentId:w?c:void 0,cronAgentName:w?b?.agentName??j?.name:void 0,cronAgentEmoji:w?A.cronAgentEmoji??b?.agentEmoji??j?.emoji:void 0,messages:L})}return console.log(`${L4} loaded ${H.length} conversations (${H.reduce((V,J)=>V+J.messages.length,0)} messages) [tail-read]`),H}var L4="[session-loader]",t0=100,D4=50,U4=3,L2=8388608,O2=134217728,F4,G4,W4,D2,K2,z4,_4,N4,E4,P4,R4,M4;var S2=OZ(()=>{q0();O0();F4=/^agent:([^:]+):botmobil[e]?:direct:(.+)$/i,G4=/^agent:([^:]+):cron:([^:]+)(?::run:([^:]+))?$/i,W4=/^agent:([^:]+):/i,D2=/^agent:conversation:([^:]+):main$/i,K2=/^botmobile:user:(.+)$/i,z4=/^\[(?:BotMobile|Botmobil[e]?) user:\S+ [^\]]+\]\s*/i,_4=/\[(?:BotMobile|Botmobil[e]?) user:\S+ [^\]]+\]\s*/gi,N4=/^\[Queued messages while agent was busy\]/i,E4=/\n\[message_id: [^\]]+\]\s*$/i,P4=/\[message_id:\s*([^\]]+)\]\s*$/i,R4=/"type"\s*:\s*"message"/,M4=/"role"\s*:\s*"([^"]+)"/});import{createRequire as v4}from"node:module";function Q0(Z){return m4[Z]??`0x${Z.toString(16)}`}function p4(){let Z=g4.version;if(typeof Z==="string"){let $=Z.trim();if($.length>0)return $}return"dev"}function C2(Z){if($1)return Buffer.from($1(Z));return Buffer.from(JSON.stringify(Z),"utf8")}function k2(Z){let $;if(X1)$=X1(Z);else{let V=Buffer.from(Z).toString("utf8");$=JSON.parse(V)}if(!$||typeof $!=="object")throw Error("Invalid wire envelope payload");let X=$,Q=typeof X.type==="bigint"?Number(X.type):X.type,Y=typeof X.seq==="bigint"?Number(X.seq):X.seq,H=typeof X.ts==="bigint"?Number(X.ts):X.ts;if(typeof Q!=="number")throw Error("Invalid wire envelope type");if(typeof Y!=="number")throw Error("Invalid wire envelope seq");if(typeof H!=="number")throw Error("Invalid wire envelope ts");return{type:Q,seq:Y,ts:H,payload:X.payload}}function PZ(Z){if(typeof Z==="number"&&Number.isFinite(Z))return Z;if(typeof Z==="bigint")return Number(Z);return null}function uZ(Z){if(typeof Z!=="string")return null;let $=Z.trim();return $.length>0?$:null}function c4(Z){if(!Array.isArray(Z))return;let $=[];for(let X of Z){if(!X||typeof X!=="object")continue;let Q=X,Y=uZ(Q.id);if(!Y)continue;let H=PZ(Q.conversationRevision),V=PZ(Q.lastMessageRevision),J=PZ(Q.lastMessageTs);$.push({id:Y,conversationRevision:H!==null?Math.max(0,Math.floor(H)):void 0,lastMessageRevision:V!==null?Math.max(0,Math.floor(V)):void 0,lastMessageTs:J!==null?Math.max(0,Math.floor(J)):void 0})}return $.length>0?$:void 0}function l4(Z){if(!Array.isArray(Z))return[];let $=[];for(let X of Z){if(!X||typeof X!=="object")continue;let Q=X,Y=uZ(Q.transferId),H=uZ(Q.fileName);if(!Y||!H)continue;$.push({transferId:Y,fileName:H,mimeType:uZ(Q.mimeType)??"application/octet-stream",size:typeof Q.size==="number"?Q.size:0})}return $}function A2(Z){if(Z.type===F.stateSyncRequest){let Q=Z.payload??{},Y=PZ(Q.stateBornAt),H=PZ(Q.globalRevision),V=c4(Q.conversations),J=[],q=PZ(Q.lastAgentTs);if(q!==null&&q>0)J.push(q);let O=PZ(Q.lastCronTs);if(O!==null&&O>0)J.push(O);if(V){for(let K of V)if(typeof K.lastMessageTs==="number"&&Number.isFinite(K.lastMessageTs)&&K.lastMessageTs>0)J.push(K.lastMessageTs)}return{kind:"legacy",envelope:{type:"state_sync_request",sinceTimestampMs:J.length>0?Math.min(...J):void 0,stateBornAt:Y!==null&&Y>0?Math.max(0,Math.floor(Y)):void 0,globalRevision:H!==null&&H>=0?Math.max(0,Math.floor(H)):void 0,conversations:V}}}if(Z.type!==F.command)return{kind:"ignore",reason:`unsupported_type_${Z.type}`};let $=Z.payload??{};if(typeof $.id!=="string"||$.id.length===0||typeof $.action!=="string")return{kind:"ignore",reason:"invalid_command_payload"};let X=$.data??{};switch($.action){case"send_message":{let Q=typeof X.conversationId==="string"?X.conversationId:"",Y=typeof X.content==="string"?X.content:"",H=typeof X.agentId==="string"&&X.agentId.length>0?X.agentId:void 0,V=typeof X.messageId==="string"&&X.messageId.length>0?X.messageId:typeof X.clientMessageId==="string"&&X.clientMessageId.length>0?X.clientMessageId:void 0;if(!Q||!Y&&!Array.isArray(X.attachments))return{kind:"ignore",reason:"invalid_send_message"};let J=l4(X.attachments);return{kind:"command",commandId:$.id,envelope:{type:"message",id:V??crypto.randomUUID(),conversationId:Q,from:"user",body:Y,timestamp:Date.now(),agentId:H,pendingAttachments:J.length>0?J:void 0}}}case"stop_generation":{let Q=typeof X.conversationId==="string"?X.conversationId:"";if(!Q)return{kind:"ignore",reason:"invalid_stop_generation"};return{kind:"command",commandId:$.id,envelope:{type:"stop_generation",conversationId:Q}}}case"cron_run":{let Q=typeof X.cronJobId==="string"?X.cronJobId:"";if(!Q)return{kind:"ignore",reason:"invalid_cron_run"};return{kind:"command",commandId:$.id,envelope:{type:"cron_run",jobId:Q}}}case"cron_toggle":{let Q=typeof X.cronJobId==="string"?X.cronJobId:"",Y=X.enabled===!0;if(!Q)return{kind:"ignore",reason:"invalid_cron_toggle"};return{kind:"command",commandId:$.id,envelope:{type:"cron_toggle",jobId:Q,enabled:Y}}}case"cron_create_from_prompt":{let Q=typeof X.agentId==="string"?X.agentId.trim():"",Y=typeof X.description==="string"?X.description.trim():"",H=typeof X.name==="string"?X.name.trim():"",V=PZ(X.everyMs),J=V!==null&&V>=60000&&V<=2592000000?Math.floor(V):void 0;if(!Q||!Y)return{kind:"ignore",reason:"invalid_cron_create_from_prompt"};return{kind:"command",commandId:$.id,envelope:{type:"cron_create_from_prompt",agentId:Q,description:Y,name:H.length>0?H:void 0,everyMs:J}}}case"client_state":{let Q=X.isForeground===!0,Y=uZ(X.activeTab),H=Y==="screen"||Y==="agents"||Y==="tasks"||Y==="settings"?Y:void 0,V=uZ(X.activeConversationId)??void 0;return{kind:"command",commandId:$.id,envelope:{type:"client_state",isForeground:Q,activeTab:H,activeConversationId:V,updatedAt:Date.now()}}}case"new_conversation":case"full_sync":return{kind:"command",commandId:$.id,envelope:{type:"state_sync_request",sinceTimestampMs:void 0}};default:return{kind:"ignore",reason:`unknown_action_${$.action}`}}}var F,m4,w2,g4,j2,$1=null,X1=null;var x2=OZ(()=>{X0();F={stateSyncRequest:1,snapshotAgents:2,snapshotCron:3,snapshotConversations:4,conversationDelta:5,streamBatch:6,streamEnd:7,command:16,commandAck:17,agentStatus:18,heartbeat:32,syncBegin:48,syncEnd:49,fileChunk:64,fileChunkAck:65,fileComplete:66,error:255},m4=Object.fromEntries(Object.entries(F).map(([Z,$])=>[$,Z]));w2=v4(import.meta.url),g4=(()=>{try{return w2("../package.json")}catch{return{}}})();j2=p4();try{let Z=w2("msgpackr"),$=new Z.Packr({useRecords:!1});$1=(X)=>$.pack(X),X1=(X)=>Z.unpack(X)}catch{}});import T2 from"node:fs";import Q1 from"node:path";import d4 from"node:os";class Y1{transfers=new Map;completed=new Map;sendWire;constructor(Z){this.sendWire=Z}handleChunk(Z){let $=this.parseChunkPayload(Z);if(!$)return;let X=this.transfers.get($.transferId);if(!X)X=this.createTransfer($),this.transfers.set($.transferId,X),console.log(`${Y0} new transfer ${$.transferId} file=${$.fileName} size=${$.totalSize} chunks=${$.totalChunks}`);X.lastActivityAt=Date.now(),this.resetTimer($.transferId,X);let Q=Buffer.isBuffer($.data)?$.data:Buffer.from($.data);if(X.receivedChunks.set($.chunkIndex,Q),this.sendWire(i4,{transferId:$.transferId,chunkIndex:$.chunkIndex}),X.receivedChunks.size>=X.totalChunks)this.finalizeTransfer($.transferId,X)}getFilePath(Z){return this.completed.get(Z)?.filePath}getCompletedTransfer(Z){return this.completed.get(Z)}dispose(){for(let[,Z]of this.transfers)clearTimeout(Z.timer);this.transfers.clear()}parseChunkPayload(Z){if(!Z||typeof Z!=="object")return null;let $=Z,X=typeof $.transferId==="string"?$.transferId.trim():"",Q=typeof $.fileName==="string"?$.fileName.trim():"",Y=typeof $.mimeType==="string"?$.mimeType.trim():"application/octet-stream",H=typeof $.totalSize==="number"?$.totalSize:0,V=typeof $.chunkIndex==="number"?$.chunkIndex:typeof $.chunkIndex==="bigint"?Number($.chunkIndex):-1,J=typeof $.totalChunks==="number"?$.totalChunks:typeof $.totalChunks==="bigint"?Number($.totalChunks):0,q=$.data;if(!X||!Q||J<=0||V<0)return null;if(!Buffer.isBuffer(q)&&!(q instanceof Uint8Array))return null;return{transferId:X,fileName:Q,mimeType:Y,totalSize:H,chunkIndex:V,totalChunks:J,data:q}}createTransfer(Z){let $=setTimeout(()=>{this.timeoutTransfer(Z.transferId)},h2);return{fileName:Z.fileName,mimeType:Z.mimeType,totalSize:Z.totalSize,totalChunks:Z.totalChunks,receivedChunks:new Map,lastActivityAt:Date.now(),timer:$}}resetTimer(Z,$){clearTimeout($.timer),$.timer=setTimeout(()=>{this.timeoutTransfer(Z)},h2)}timeoutTransfer(Z){let $=this.transfers.get(Z);if(!$)return;console.warn(`${Y0} transfer ${Z} timed out (received ${$.receivedChunks.size}/${$.totalChunks} chunks)`),clearTimeout($.timer),this.transfers.delete(Z),this.sendWire(W0,{transferId:Z,success:!1,error:"Transfer timed out"})}finalizeTransfer(Z,$){clearTimeout($.timer),this.transfers.delete(Z);let X=[];for(let V=0;V<$.totalChunks;V++){let J=$.receivedChunks.get(V);if(!J){console.error(`${Y0} transfer ${Z} missing chunk ${V}`),this.sendWire(W0,{transferId:Z,success:!1,error:`Missing chunk ${V}`});return}X.push(J)}let Q=Buffer.concat(X),Y=Q1.basename($.fileName).replace(/[^\w.\-]/g,"_")||"file",H=Q1.join(b2,`${Z}-${Y}`);try{T2.mkdirSync(b2,{recursive:!0}),T2.writeFileSync(H,Q)}catch(V){console.error(`${Y0} transfer ${Z} write failed: ${String(V)}`),this.sendWire(W0,{transferId:Z,success:!1,error:`Write failed: ${String(V)}`});return}this.completed.set(Z,{fileName:$.fileName,mimeType:$.mimeType,filePath:H,size:Q.length}),console.log(`${Y0} transfer ${Z} complete: ${H} (${Q.length} bytes)`),this.sendWire(W0,{transferId:Z,success:!0})}}var Y0="[botmobile:file-receiver]",h2=60000,b2,i4=65,W0=66;var f2=OZ(()=>{b2=Q1.join(d4.homedir(),".openclaw","uploads")});import vZ from"ws";function V5(Z){return new Promise(($)=>setTimeout($,Z))}async function J5(){if(!z0)z0=import("node-datachannel");let Z;try{Z=await z0}catch($){z0=null;let X=String($??"");if(X.includes("node_datachannel.node")||X.includes("Cannot find module '../../../build/Release/node_datachannel.node'"))throw Error("node-datachannel native binary is missing. Run: cd ~/.openclaw/extensions/botmobile-openclaw && npm rebuild");throw $}if(!v2){v2=!0;try{Z.initLogger?.("Error")}catch{}}return Z}function S(Z){if(typeof Z!=="string")return null;let $=Z.trim();return $.length>0?$:null}function q5(Z){if(typeof Z==="string"){let Q=Z.trim();if(!Q)return null;return{candidate:Q}}if(!Z||typeof Z!=="object")return null;let $=Z,X=S($.candidate);if(!X)return null;return{candidate:X,sdpMid:S($.sdpMid)??void 0}}function O5(Z){if(!Z||typeof Z!=="object")return["stun:stun.cloudflare.com:3478"];let X=Z,Q=Array.isArray(X.urls)?X.urls.filter((J)=>typeof J==="string"&&J.trim().length>0):typeof X.urls==="string"?X.urls.split(",").map((J)=>J.trim()).filter((J)=>J.length>0):[],Y=S(X.username),H=S(X.credential);if(Q.length===0||!Y||!H)return["stun:stun.cloudflare.com:3478"];let V=["stun:stun.cloudflare.com:3478"];for(let J of Q){let q=K5(J);if(!q)continue;V.push({hostname:q.hostname,port:q.port,username:Y,password:H,relayType:q.relayType})}return V}function K5(Z){let $=Z.match(/^(turns?):([^:?]+):(\d+)/);if(!$)return null;let X=$[1],Q=$[2],Y=parseInt($[3],10),V=Z.match(/[?&]transport=(udp|tcp)/i)?.[1]?.toLowerCase()??"udp",J;if(X==="turns")J="TurnTls";else if(V==="tcp")J="TurnTcp";else J="TurnUdp";return{hostname:Q,port:Y,relayType:J}}function B5(Z){return{id:Z.id,conversationId:Z.conversationId,role:Z.from==="user"?"user":"bot",content:Z.body,timestamp:Z.timestamp,isStreaming:!1}}function L5(Z){if(!Z)return;return{...Z,skills:Z.skills?[...Z.skills]:void 0,skillDetails:Z.skillDetails?Z.skillDetails.map(($)=>({...$})):void 0,toolsAllow:Z.toolsAllow?[...Z.toolsAllow]:void 0,toolsDeny:Z.toolsDeny?[...Z.toolsDeny]:void 0}}function D5(Z){let $=Z.status==="working";return{id:Z.agentId,name:Z.name,emoji:Z.emoji,color:Z.color,details:L5(Z.details),queue:$?1:0,lastUpdated:Z.lastActivityAt??Date.now(),usage:{mode:"tokens",value:Math.max(0,(Z.sessionTokensIn??0)+(Z.sessionTokensOut??0))},isRunning:$,currentTask:Z.activeTool}}function U5(Z){return{id:Z.id,name:Z.name,enabled:Z.enabled,isRunning:Z.isRunning===!0,lastUpdated:Date.now(),agentId:Z.agentId,agentName:Z.agentName,agentEmoji:Z.agentEmoji,nextRunAt:Z.nextRunAt,lastRunAt:Z.lastRunAt,lastRunStatus:Z.lastRunStatus,lastRunSummary:Z.lastRunSummary}}function F5(Z){switch(Z.type){case"message":return[{type:F.conversationDelta,payload:{id:Z.conversationId,updatedAt:Z.timestamp,messages:[B5(Z)]}}];case"conversation_list":{let $=Date.now();return[{type:F.snapshotConversations,payload:{timestamp:$,conversations:Z.conversations.map((X)=>{let Q=o0(X.id);return{id:X.id,name:X.name,agent:Q?.agent,createdAt:X.createdAt??Q?.createdAt??$,updatedAt:X.lastActivity??Q?.updatedAt??$,revision:Q?.revision,lastMessageRevision:Q?.lastMessageRevision,activity:Q?.activity}})}}]}case"agent_list":return[{type:F.snapshotAgents,payload:{timestamp:Date.now(),agents:Z.agents.map(D5)}}];case"agent_status":return[{type:F.agentStatus,payload:{id:Z.agentId,activeConversationId:Z.activeConversationId,isRunning:Z.status==="working",queue:Z.status==="working"?1:0,color:Z.color,details:Z.details,currentTask:Z.activeTool,lastUpdated:Z.lastActivityAt??Date.now(),usage:{mode:"tokens",value:Math.max(0,(Z.sessionTokensIn??0)+(Z.sessionTokensOut??0))},errorMessage:Z.errorMessage}}];case"cron_list":return[{type:F.snapshotCron,payload:{timestamp:Date.now(),cronJobs:Z.jobs.map(U5)}}];case"state_snapshot":case"state_delta":{let $=[],X=crypto.randomUUID().slice(0,8),Q=Z.state.conversations.length;$.push({type:F.syncBegin,payload:{syncId:X,totalConversations:Q,pluginVersion:j2,stateBornAt:Z.state.stateBornAt,globalRevision:Z.state.globalRevision}}),$.push({type:F.snapshotAgents,payload:{timestamp:Z.state.timestamp,stateBornAt:Z.state.stateBornAt,globalRevision:Z.state.globalRevision,agents:Z.state.agents}}),$.push({type:F.snapshotCron,payload:{timestamp:Z.state.timestamp,stateBornAt:Z.state.stateBornAt,globalRevision:Z.state.globalRevision,cronJobs:Z.state.cronJobs}}),$.push({type:F.snapshotConversations,payload:{timestamp:Z.state.timestamp,stateBornAt:Z.state.stateBornAt,globalRevision:Z.state.globalRevision,conversations:Z.state.conversations.map((Y)=>({id:Y.id,kind:Y.kind,cronJobId:Y.cronJobId,cronName:Y.cronName,cronAgentId:Y.cronAgentId,cronAgentName:Y.cronAgentName,cronAgentEmoji:Y.cronAgentEmoji,agent:Y.agent,createdAt:Y.createdAt,updatedAt:Y.updatedAt,revision:Y.revision,lastMessageRevision:Y.lastMessageRevision,activity:Y.activity}))}});for(let Y of Z.state.conversations)$.push({type:F.conversationDelta,payload:{id:Y.id,kind:Y.kind,cronJobId:Y.cronJobId,cronName:Y.cronName,cronAgentId:Y.cronAgentId,cronAgentName:Y.cronAgentName,cronAgentEmoji:Y.cronAgentEmoji,agent:Y.agent,createdAt:Y.createdAt,updatedAt:Y.updatedAt,revision:Y.revision,lastMessageRevision:Y.lastMessageRevision,activity:Y.activity,messages:Y.messages}});return $.push({type:F.syncEnd,payload:{syncId:X,sentConversations:Q,stateBornAt:Z.state.stateBornAt,globalRevision:Z.state.globalRevision}}),$}case"gateway_heartbeat":return[{type:F.heartbeat,payload:{kind:"gateway",timestamp:Z.timestamp,uptimeMs:Z.uptimeMs}}];case"error":return[{type:F.error,payload:{code:Z.code,message:Z.message,conversationId:Z.conversationId}}];case"ping":case"pong":default:return[]}}function m2(Z,$){if(Z===F.heartbeat)return"";if(!$||typeof $!=="object")return String($??"");let X=$;switch(Z){case F.conversationDelta:{let Q=Array.isArray(X.messages)?X.messages.length:0;return`conv=${S(X.id)??"?"} msgs=${Q}`}case F.snapshotAgents:return`agents=${Array.isArray(X.agents)?X.agents.length:0}`;case F.snapshotCron:return`jobs=${Array.isArray(X.cronJobs)?X.cronJobs.length:0}`;case F.snapshotConversations:return`conversations=${Array.isArray(X.conversations)?X.conversations.length:0}`;case F.streamBatch:return`conv=${S(X.conversationId)??"?"} msg=${S(X.messageId)?.slice(0,8)??"?"} +${(S(X.tokens)??"").length}ch`;case F.streamEnd:return`conv=${S(X.conversationId)??"?"} msg=${S(X.messageId)?.slice(0,8)??"?"} len=${(S(X.finalContent)??"").length}`;case F.command:return`action=${S(X.action)??"?"} id=${S(X.id)??"?"}`;case F.commandAck:return`id=${S(X.commandId)??"?"} ok=${X.ok}`;case F.agentStatus:return`agent=${S(X.id)??"?"} running=${X.isRunning}`;case F.syncBegin:return`syncId=${S(X.syncId)??"?"} total=${X.totalConversations}`;case F.syncEnd:return`syncId=${S(X.syncId)??"?"} sent=${X.sentConversations}`;case F.error:return`code=${S(X.code)??"?"} msg=${S(X.message)??"?"}`;case F.stateSyncRequest:return`globalRevision=${X.globalRevision??"nil"} stateBornAt=${X.stateBornAt??"nil"}`;default:return JSON.stringify($).slice(0,120)}}class H1{account;onLegacyEnvelope;onSignalingStatus;onDataChannelStatus;signalingWs=null;peerConnection=null;dataChannel=null;currentSessionId=null;currentOfferRequestId=null;outboundSeq=1;outboundQueue=[];outboundQueueBytes=0;streamTextByMessageId=new Map;pendingStreamBatches=new Map;dataChannelDisconnectedAt=null;awaitingStateSyncRequest=!1;heartbeatInterval=null;lastHeartbeatReceivedAt=0;lastHeartbeatRttMs=null;lastPushSentAt=0;clientIsForeground=null;clientStateUpdatedAt=0;pendingPushTimer=null;pendingPushRequest=null;resyncRequired=!1;pendingRemoteCandidates=[];remoteDescriptionApplied=!1;pendingSignalQueue=[];signalingHeartbeatInterval=null;lastSignalingPongAt=0;stopped=!1;answerGatherTimer=null;_fileReceiver=null;lastSnapshotSignatureByType=new Map;lastSnapshotSentAtByType=new Map;constructor(Z){this.account=Z.account,this.onLegacyEnvelope=Z.onLegacyEnvelope,this.onSignalingStatus=Z.onSignalingStatus,this.onDataChannelStatus=Z.onDataChannelStatus}get fileReceiver(){return this._fileReceiver}async run(Z){let $=I2;while(!Z.aborted&&!this.stopped){try{await this.connectSignalingOnce(Z),$=I2}catch(X){console.error(`${G} signaling loop error: ${String(X)}`)}if(Z.aborted||this.stopped)break;await V5($),$=Math.min($*2,r4)}this.cleanup()}stop(){this.stopped=!0,this.cleanup()}sendLegacyEnvelope(Z){if(Z.type==="stream_start"){this.handleLegacyStreamStart(Z);return}if(Z.type==="stream_token"){this.handleLegacyStreamToken(Z);return}if(Z.type==="stream_end"){this.handleLegacyStreamEnd(Z);return}let $=F5(Z);for(let X of $)this.sendWire(X.type,X.payload)}async connectSignalingOnce(Z){let $=`${this.account.workerUrl.replace(/^http/,"ws")}/ws/signal`;await new Promise((X,Q)=>{let Y=!1,H=null,V=new vZ($,{headers:{authorization:`BotMobileSecret ${this.account.sharedSecret}`}});this.signalingWs=V;let J=(q)=>{if(Y)return;if(Y=!0,H)Z.removeEventListener("abort",H),H=null;q()};H=()=>{this.stopSignalingHeartbeat();try{V.close()}catch{}J(()=>X())},Z.addEventListener("abort",H,{once:!0}),V.on("open",()=>{this.onSignalingStatus?.(!0),this.startSignalingHeartbeat(),this.flushPendingSignalQueue()}),V.on("message",(q)=>{let O=q.toString(),B;try{B=JSON.parse(O)}catch{console.warn(`${G} invalid signaling message`);return}this.handleSignalingMessage(B).catch((K)=>{console.error(`${G} signaling message handler failed: ${String(K)}`)})}),V.on("close",()=>{this.stopSignalingHeartbeat(),this.onSignalingStatus?.(!1),this.signalingWs=null,J(()=>X())}),V.on("error",(q)=>{this.stopSignalingHeartbeat(),this.onSignalingStatus?.(!1),this.signalingWs=null,J(()=>Q(q))})})}async handleSignalingMessage(Z){if(!Z||typeof Z!=="object")return;let $=Z;if($.type==="pong"){this.lastSignalingPongAt=Date.now();return}if($.type==="ping"){this.sendSignal({type:"pong",ts:Date.now()});return}if($.type==="offer"){await this.handleOffer(Z);return}if($.type==="ice"){this.handleRemoteIce(Z);return}if($.type==="error")console.warn(`${G} signaling error: ${JSON.stringify(Z)}`)}sendSignalingPing(){let Z=this.signalingWs;if(!Z||Z.readyState!==vZ.OPEN)return;try{Z.send(JSON.stringify({type:"ping",ts:Date.now()}))}catch($){console.warn(`${G} signaling ping send failed: ${String($)}`);try{Z.close()}catch{}}}startSignalingHeartbeat(){this.stopSignalingHeartbeat(),this.lastSignalingPongAt=Date.now(),this.sendSignalingPing(),this.signalingHeartbeatInterval=setInterval(()=>{let Z=this.signalingWs;if(!Z||Z.readyState!==vZ.OPEN)return;if(Date.now()-this.lastSignalingPongAt>$5){console.warn(`${G} signaling heartbeat stale; forcing reconnect`);try{Z.close()}catch{}return}this.sendSignalingPing()},Z5)}stopSignalingHeartbeat(){if(this.signalingHeartbeatInterval)clearInterval(this.signalingHeartbeatInterval),this.signalingHeartbeatInterval=null;this.lastSignalingPongAt=0}async handleOffer(Z){let $=S(Z.requestId),X=S(Z.sdp);if(!$||!X){this.sendSignal({type:"error",requestId:Z.requestId,code:"INVALID_OFFER",message:"Offer payload is missing requestId or sdp"},{queueIfClosed:!0});return}if(this.answerGatherTimer)clearTimeout(this.answerGatherTimer),this.answerGatherTimer=null;if(this.peerConnection||this.dataChannel)console.log(`${G} closing stale peer connection before new offer`),this.closePeerConnection();this.currentOfferRequestId=$,this.currentSessionId=Z.sessionId??crypto.randomUUID().replace(/-/g,""),this.pendingRemoteCandidates=[],this.remoteDescriptionApplied=!1,this.awaitingStateSyncRequest=!0;let Q;try{Q=await this.ensurePeerConnection(Z.turnCredentials)}catch(Y){console.error(`${G} peer connection creation failed requestId=${$} error=${String(Y)}`),this.sendSignal({type:"error",requestId:$,code:"PEER_CREATE_FAILED",message:String(Y)},{queueIfClosed:!0});return}try{console.log(`${G} setRemoteDescription offer sdp_len=${X.length} ice_candidates=${Array.isArray(Z.iceCandidates)?Z.iceCandidates.length:0}`);let H=(X.split(`\r
6
+ `).length>1?X.split(`\r
7
+ `):X.split(`
8
+ `)).filter((V)=>V.startsWith("a=ice-")||V.startsWith("a=fingerprint")||V.startsWith("a=setup")||V.startsWith("m="));if(console.log(`${G} SDP ice-relevant lines: ${H.join(" | ")}`),Q.setRemoteDescription?.(X,"offer"),this.remoteDescriptionApplied=!0,console.log(`${G} setRemoteDescription success`),Array.isArray(Z.iceCandidates))for(let V of Z.iceCandidates)this.enqueuePendingRemoteCandidate(V,this.currentSessionId??void 0);this.flushPendingRemoteCandidates(),Q.setLocalDescription?.(),console.log(`${G} setLocalDescription (answer) triggered`)}catch(Y){console.error(`${G} offer processing failed: ${String(Y)}`),this.sendSignal({type:"error",requestId:$,code:"OFFER_PROCESS_FAILED",message:String(Y)},{queueIfClosed:!0})}}async ensurePeerConnection(Z){if(this.peerConnection)return this.peerConnection;let $=await J5(),X={iceServers:O5(Z)},Q=new $.PeerConnection(`botmobile-${Date.now()}`,X);this.peerConnection=Q,this.dataChannelDisconnectedAt=Date.now(),this.awaitingStateSyncRequest=!0;let Y=[],H=null,V=this.currentOfferRequestId,J=this.currentSessionId,q=()=>{if(this.answerGatherTimer)clearTimeout(this.answerGatherTimer),this.answerGatherTimer=null;if(this.peerConnection!==Q)return;if(!H)return;let O=H;H=null,console.log(`${G} sending answer with ${Y.length} bundled candidates`),this.sendSignal({type:"answer",requestId:V,sessionId:J,sdp:O,iceCandidates:Y.slice()},{queueIfClosed:!0})};return Q.onLocalDescription?.((O,B)=>{if(this.peerConnection!==Q)return;if(console.log(`${G} onLocalDescription type=${B} sdp_len=${O?.length??0} requestId=${V} wsOpen=${this.signalingWs?.readyState===vZ.OPEN}`),B!=="answer")return;H=O,this.answerGatherTimer=setTimeout(q,X5)}),Q.onLocalCandidate?.((O,B)=>{if(this.peerConnection!==Q)return;if(!O)return;if(H)Y.push({candidate:O,sdpMid:B});else this.sendSignal({type:"ice",sessionId:this.currentSessionId,candidate:{candidate:O,sdpMid:B}},{queueIfClosed:!0})}),Q.onStateChange?.((O)=>{if(this.peerConnection!==Q)return;if(O==="failed"||O==="closed"||O==="disconnected"){if(this.onDataChannelStatus?.(!1),this.dataChannelDisconnectedAt===null)this.dataChannelDisconnectedAt=Date.now();this.clientIsForeground=!1,this.clientStateUpdatedAt=Date.now()}}),Q.onDataChannel?.((O)=>{if(this.peerConnection!==Q)return;console.log(`${G} onDataChannel fired — received remote data channel`),this.attachDataChannel(O)}),Q}attachDataChannel(Z){if(console.log(`${G} attachDataChannel called`),this.dataChannel&&this.dataChannel!==Z)try{this.dataChannel.close?.()}catch{}this.dataChannel=Z,Z.onOpen?.(()=>{if(this.dataChannel!==Z)return;console.log(`${G} dataChannel onOpen fired`),this.onDataChannelStatus?.(!0),this.dataChannelDisconnectedAt=null,this.clientIsForeground=!0,this.clientStateUpdatedAt=Date.now(),this.awaitingStateSyncRequest=!0,this.startHeartbeatLoop(),this.sendHeartbeat("ping")}),Z.onClosed?.(()=>{if(this.dataChannel!==Z)return;if(console.log(`${G} dataChannel onClosed fired`),this.dataChannel=null,this.onDataChannelStatus?.(!1),this.stopHeartbeatLoop(),this.dataChannelDisconnectedAt===null)this.dataChannelDisconnectedAt=Date.now();this.clientIsForeground=!1,this.clientStateUpdatedAt=Date.now()}),Z.onError?.(($)=>{if(this.dataChannel!==Z)return;console.error(`${G} datachannel error: ${String($)}`),this.dataChannel=null}),Z.onMessage?.(($)=>{if(this.dataChannel!==Z)return;let X=$===null?"null":typeof $==="object"?$.constructor?.name??"object":typeof $,Q=Buffer.isBuffer($)?$.length:$ instanceof ArrayBuffer?$.byteLength:ArrayBuffer.isView($)?$.byteLength:typeof $==="string"?$.length:-1;console.log(`${G} dataChannel onMessage: type=${X} len=${Q}`),this.handleDataChannelMessage($)})}handleDataChannelMessage(Z){let $;if(Buffer.isBuffer(Z))$=Z;else if(typeof Z==="string")$=Buffer.from(Z,"binary");else if(Z instanceof ArrayBuffer)$=Buffer.from(Z);else if(ArrayBuffer.isView(Z))$=Buffer.from(Z.buffer,Z.byteOffset,Z.byteLength);else return;let X;try{X=k2($);let Y=Q0(X.type);if(X.type!==F.heartbeat)console.log(`${G} ◀ RECV ${Y} ${m2(X.type,X.payload)}`)}catch(Y){console.error(`${G} wire decode failed: ${String(Y)} hex=${$.subarray(0,32).toString("hex")}`),this.sendWire(F.error,{code:"INVALID_WIRE_ENVELOPE",message:String(Y)});return}if(this.lastHeartbeatReceivedAt=Date.now(),X.type===F.heartbeat){this.handleHeartbeatPayload(X.payload);return}if(X.type===F.fileChunk){this.ensureFileReceiver().handleChunk(X.payload);return}let Q=A2(X);if(Q.kind==="ignore")return;if(Q.kind==="command")this.sendWire(F.commandAck,{commandId:Q.commandId,ok:!0});if(Q.envelope.type==="client_state")this.clientIsForeground=Q.envelope.isForeground===!0,this.clientStateUpdatedAt=Date.now(),console.log(`${G} client_state foreground=${this.clientIsForeground} tab=${Q.envelope.activeTab??"unknown"} conv=${Q.envelope.activeConversationId??"none"}`);if(this.onLegacyEnvelope(Q.envelope),Q.envelope.type==="state_sync_request")this.resyncRequired=!1,this.awaitingStateSyncRequest=!1,this.flushOutboundQueue()}handleRemoteIce(Z){if(!this.currentSessionId)return;let $=S(Z.sessionId);if($&&$!==this.currentSessionId)return;if(!this.peerConnection||!this.remoteDescriptionApplied){this.enqueuePendingRemoteCandidate(Z.candidate,$??void 0);return}this.addRemoteCandidate(Z.candidate)}enqueuePendingRemoteCandidate(Z,$){if(this.pendingRemoteCandidates.length>=128)this.pendingRemoteCandidates.shift();this.pendingRemoteCandidates.push({sessionId:$,candidate:Z})}addRemoteCandidate(Z){let $=q5(Z);if(!$)return;try{this.peerConnection?.addRemoteCandidate?.($.candidate,$.sdpMid)}catch(X){console.warn(`${G} addRemoteCandidate failed: ${String(X)}`)}}flushPendingRemoteCandidates(){if(!this.peerConnection||!this.currentSessionId||this.pendingRemoteCandidates.length===0)return;let Z=this.pendingRemoteCandidates;this.pendingRemoteCandidates=[];for(let $ of Z){if($.sessionId&&$.sessionId!==this.currentSessionId)continue;this.addRemoteCandidate($.candidate)}}enqueuePendingSignal(Z){if(this.pendingSignalQueue.length>=Q5)this.pendingSignalQueue.shift();this.pendingSignalQueue.push(Z)}flushPendingSignalQueue(){if(!this.signalingWs||this.signalingWs.readyState!==vZ.OPEN)return;if(this.pendingSignalQueue.length>0)console.log(`${G} flushing queued signaling messages count=${this.pendingSignalQueue.length}`);while(this.pendingSignalQueue.length>0){let Z=this.pendingSignalQueue[0];try{this.signalingWs.send(JSON.stringify(Z)),this.pendingSignalQueue.shift()}catch($){console.warn(`${G} signaling queued send failed: ${String($)}`);return}}}sendSignal(Z,$={}){let X=String(Z.type??"unknown"),Q=typeof Z.requestId==="string"?Z.requestId:void 0,Y=typeof Z.code==="string"?Z.code:void 0,H=typeof Z.message==="string"?Z.message:void 0,V=X==="error"?` requestId=${Q??"n/a"} code=${Y??"n/a"} message=${H??"n/a"}`:"";if(!this.signalingWs||this.signalingWs.readyState!==vZ.OPEN){if($.queueIfClosed)this.enqueuePendingSignal(Z),console.warn(`${G} sendSignal queued type=${X}${V} readyState=${this.signalingWs?.readyState??"null"}`);else console.warn(`${G} sendSignal DROPPED type=${X}${V} readyState=${this.signalingWs?.readyState??"null"}`);return!1}try{return console.log(`${G} sendSignal type=${X}${V}`),this.signalingWs.send(JSON.stringify(Z)),!0}catch(J){if($.queueIfClosed)this.enqueuePendingSignal(Z);return console.warn(`${G} signaling send failed: ${String(J)}`),!1}}sendWire(Z,$){if(this.shouldDropSnapshot(Z,$))return;let X=Q0(Z);if(Z!==F.heartbeat)console.log(`${G} ▶ SEND ${X} ${m2(Z,$)}`);let Q={type:Z,seq:this.outboundSeq++,ts:Date.now(),payload:$},Y=C2(Q),H=Z===F.heartbeat||Z===F.error;if(this.dataChannel!==null&&(!this.awaitingStateSyncRequest||H)&&this.trySendDataChannelBytes(Y)){this.maybeTriggerPush(Z,$);return}if(Z===F.heartbeat)return;if(this.resyncRequired&&Z!==F.error)return;this.enqueueOutbound({bytes:Y,type:Z,payload:$}),this.maybeTriggerPush(Z,$)}trySendDataChannelBytes(Z){let $=this.dataChannel;if(!$)return console.log(`${G} trySend: no dataChannel`),!1;try{if(typeof $.sendMessageBinary==="function")return $.sendMessageBinary(Z),console.log(`${G} trySend: sendMessageBinary ${Z.length}B ok`),!0;if(typeof $.sendMessage==="function")return $.sendMessage(Z),console.log(`${G} trySend: sendMessage ${Z.length}B ok`),!0;if(typeof $.send==="function")return $.send(Z),console.log(`${G} trySend: send ${Z.length}B ok`),!0}catch(X){return console.error(`${G} trySend error: ${String(X)}`),!1}return console.warn(`${G} trySend: no send method available on channel`),!1}enqueueOutbound(Z){let $=Z.bytes.byteLength;if($>y2){this.markResyncRequired("Outbound item exceeded queue byte limit; full sync required.");return}if(this.isSnapshotWireType(Z.type)){let Q=this.outboundQueue.findIndex((Y)=>Y.type===Z.type);if(Q>=0){let Y=this.outboundQueue[Q];this.outboundQueue[Q]=Z,this.outboundQueueBytes=Math.max(0,this.outboundQueueBytes-Y.bytes.byteLength+$);return}}let X=!1;while(this.outboundQueue.length>=s4||this.outboundQueueBytes+$>y2){let Q=this.outboundQueue.findIndex((J)=>!this.isSnapshotWireType(J.type)),Y=Q>=0?Q:0,V=this.outboundQueue.splice(Y,1)[0];if(!V)break;this.outboundQueueBytes=Math.max(0,this.outboundQueueBytes-V.bytes.byteLength),X=!0}if(X){this.markResyncRequired("Outbound queue overflowed; full sync required.");return}this.outboundQueue.push(Z),this.outboundQueueBytes+=$}markResyncRequired(Z){if(this.resyncRequired)return;this.resyncRequired=!0,this.awaitingStateSyncRequest=!0,this.outboundQueue=[],this.outboundQueueBytes=0,this.sendWire(F.error,{code:"RESYNC_REQUIRED",message:Z})}flushOutboundQueue(){if(!this.dataChannel)return;if(this.awaitingStateSyncRequest)return;while(this.outboundQueue.length>0){let Z=this.outboundQueue[0];if(!this.trySendDataChannelBytes(Z.bytes))return;this.outboundQueue.shift(),this.outboundQueueBytes=Math.max(0,this.outboundQueueBytes-Z.bytes.byteLength)}}isSnapshotWireType(Z){return Z===F.snapshotAgents||Z===F.snapshotCron||Z===F.snapshotConversations}snapshotSignature(Z,$){if(!this.isSnapshotWireType(Z)||!$||typeof $!=="object")return null;let X=$;if(Z===F.snapshotAgents)return JSON.stringify({agents:this.normalizeSnapshotValue(Array.isArray(X.agents)?X.agents:[])});if(Z===F.snapshotCron)return JSON.stringify({cronJobs:this.normalizeCronJobsForSignature(X.cronJobs)});if(Z===F.snapshotConversations)return JSON.stringify({conversations:this.normalizeSnapshotValue(Array.isArray(X.conversations)?X.conversations:[])});return null}normalizeSnapshotValue(Z){if(Array.isArray(Z))return Z.map((Y)=>this.normalizeSnapshotValue(Y));if(!Z||typeof Z!=="object")return Z;let $=Z,X={},Q=Object.keys($).sort();for(let Y of Q){if(Y==="timestamp"||Y==="lastUpdated"||Y==="runningElapsedMs"||Y==="nextRunAt")continue;X[Y]=this.normalizeSnapshotValue($[Y])}return X}normalizeCronJobsForSignature(Z){if(!Array.isArray(Z))return[];let $=[];for(let X of Z){if(!X||typeof X!=="object")continue;let Q=X;$.push({id:this.normalizeSnapshotValue(Q.id),name:this.normalizeSnapshotValue(Q.name),enabled:Q.enabled===!0,isRunning:Q.isRunning===!0,agentId:this.normalizeSnapshotValue(Q.agentId),agentName:this.normalizeSnapshotValue(Q.agentName),agentEmoji:this.normalizeSnapshotValue(Q.agentEmoji),schedule:this.normalizeSnapshotValue(Q.schedule),lastRunAt:this.normalizeSnapshotValue(Q.lastRunAt),lastRunStatus:this.normalizeSnapshotValue(Q.lastRunStatus),lastRunSummary:this.normalizeSnapshotValue(Q.lastRunSummary)})}return $.sort((X,Q)=>String(X.id??"").localeCompare(String(Q.id??""))),$}shouldDropSnapshot(Z,$){let X=this.snapshotSignature(Z,$);if(!X)return!1;let Q=Date.now(),Y=this.lastSnapshotSignatureByType.get(Z),H=this.lastSnapshotSentAtByType.get(Z)??0;if(Z===F.snapshotCron&&H>0&&Q-H<H5)return!0;if(Y===X&&Q-H<Y5)return!0;return this.lastSnapshotSignatureByType.set(Z,X),this.lastSnapshotSentAtByType.set(Z,Q),!1}streamKey(Z,$){return`${Z}:${$}`}handleLegacyStreamStart(Z){let $=this.streamKey(Z.conversationId,Z.messageId);this.streamTextByMessageId.set($,"");let X=this.pendingStreamBatches.get($);if(X?.timer)clearTimeout(X.timer);this.pendingStreamBatches.delete($)}handleLegacyStreamToken(Z){if(!Z.token)return;let $=this.streamKey(Z.conversationId,Z.messageId),X=this.streamTextByMessageId.get($)??"";this.streamTextByMessageId.set($,X+Z.token);let Q=this.pendingStreamBatches.get($);if(Q){Q.tokens+=Z.token;return}let Y={conversationId:Z.conversationId,messageId:Z.messageId,offset:X.length,tokens:Z.token,timer:null};Y.timer=setTimeout(()=>{this.flushStreamBatch($)},t4),this.pendingStreamBatches.set($,Y)}handleLegacyStreamEnd(Z){let $=this.streamKey(Z.conversationId,Z.messageId);this.flushStreamBatch($);let X=this.streamTextByMessageId.get($)??"",Q=Z.body&&Z.body.length>0?Z.body:X;this.streamTextByMessageId.delete($),this.pendingStreamBatches.delete($),this.sendWire(F.streamEnd,{conversationId:Z.conversationId,messageId:Z.messageId,finalContent:Q})}flushStreamBatch(Z){let $=this.pendingStreamBatches.get(Z);if(!$)return;if($.timer)clearTimeout($.timer),$.timer=null;if($.tokens.length>0)this.sendWire(F.streamBatch,{conversationId:$.conversationId,messageId:$.messageId,offset:$.offset,tokens:$.tokens});this.pendingStreamBatches.delete(Z)}flushAllStreamBatches(){for(let Z of Array.from(this.pendingStreamBatches.keys()))this.flushStreamBatch(Z)}sendHeartbeat(Z,$){console.log(`${G} sendHeartbeat kind=${Z}`),this.sendWire(F.heartbeat,{kind:Z,sentAt:$??Date.now()})}handleHeartbeatPayload(Z){let $=S(Z.kind),X=Z.sentAt,Q=typeof X==="number"&&Number.isFinite(X)?X:typeof X==="bigint"?Number(X):Date.now();if($==="ping"){this.sendHeartbeat("pong",Q);return}if($==="pong"){this.lastHeartbeatRttMs=Math.max(0,Date.now()-Q);return}}startHeartbeatLoop(){this.stopHeartbeatLoop(),this.lastHeartbeatReceivedAt=Date.now(),this.heartbeatInterval=setInterval(()=>{if(!this.dataChannel)return;if(Date.now()-this.lastHeartbeatReceivedAt>e4){console.warn(`${G} heartbeat stale (rtt=${this.lastHeartbeatRttMs??-1}ms), closing peer`),this.closePeerConnection(),this.onDataChannelStatus?.(!1),this.dataChannelDisconnectedAt=Date.now(),this.clientIsForeground=!1,this.clientStateUpdatedAt=Date.now();return}this.sendHeartbeat("ping")},a4)}stopHeartbeatLoop(){if(this.heartbeatInterval)clearInterval(this.heartbeatInterval),this.heartbeatInterval=null}pushPriority(Z){if(Z===F.error)return 5;if(Z===F.streamEnd)return 4;if(Z===F.conversationDelta)return 3;if(Z===F.agentStatus)return 1;return 0}queuePushTrigger(Z,$){let X=this.pushPriority(Z),Q=this.pendingPushRequest;if(!Q||X>=Q.priority)this.pendingPushRequest={type:Z,pushInfo:$,priority:X};if(this.pendingPushTimer)return;this.pendingPushTimer=setTimeout(()=>{this.flushPendingPush()},n4)}async flushPendingPush(){this.pendingPushTimer=null;let Z=this.pendingPushRequest;if(this.pendingPushRequest=null,!Z)return;let $=Date.now(),X=$-this.lastPushSentAt;if(X<u2){this.pendingPushRequest=Z,this.pendingPushTimer=setTimeout(()=>{this.flushPendingPush()},u2-X);return}this.lastPushSentAt=$;try{let Q=await fetch(`${this.account.workerUrl}/api/push`,{method:"POST",headers:{"content-type":"application/json",authorization:`BotMobilePush ${this.account.pushSecret}`},body:JSON.stringify(Z.pushInfo)});if(!Q.ok){let H=(await Q.text().catch(()=>"")).trim();console.warn(`${G} push trigger failed status=${Q.status}${H?` body=${H.slice(0,200)}`:""}`)}else console.log(`${G} push triggered type=${Q0(Z.type)} foreground=${this.clientIsForeground??"unknown"} stateAgeMs=${$-this.clientStateUpdatedAt}`)}catch(Q){console.warn(`${G} push trigger error=${String(Q)}`)}}async maybeTriggerPush(Z,$){let X=this.pushInfoForEvent(Z,$);if(!X)return;if(!this.account.pushSecret||this.account.pushSecret.trim().length===0)return;let Q=Date.now(),Y=this.dataChannelDisconnectedAt!==null?Q-this.dataChannelDisconnectedAt:null,H=Y!==null&&Y>=o4;if(this.clientIsForeground!==!1&&!H){console.log(`${G} push skipped type=${Q0(Z)} foreground=${this.clientIsForeground??"unknown"} disconnectedForMs=${Y??-1}`);return}this.queuePushTrigger(Z,X)}normalizedPushAgentName(Z){if(typeof Z!=="string")return null;let $=Z.trim();if(!$)return null;if($.toLowerCase().startsWith("conversation:"))return null;return $}pushTitleForConversation(Z,$){let X=this.normalizedPushAgentName($);if(X)return X;if(Z){let Q=o0(Z),Y=this.normalizedPushAgentName(Q?.agent?.name);if(Y)return Y}return"Assistant"}pushInfoForEvent(Z,$){if(Z===F.error){let X=$;return{title:"BotMobile error",body:S(X.message)??"An error occurred",data:{conversationId:S(X.conversationId)??""}}}if(Z===F.agentStatus){let X=$;if(X.isRunning===!1)return{title:"Agent update",body:"An agent run finished while you were away.",data:{agentId:S(X.id)??""}}}if(Z===F.conversationDelta){let X=$,Q=S(X.id)??"",Y=X.agent;if(Array.isArray(X.messages)&&X.messages.length>0){let H=X.messages[X.messages.length-1];if(H.role==="bot"){let V=S(H.content)??"",J=V.length>120?V.slice(0,120)+"…":V;return{title:this.pushTitleForConversation(Q,Y?.name),body:J||"You have a new message.",data:{conversationId:Q}}}}}if(Z===F.streamEnd){let X=$,Q=S(X.conversationId)??"",Y=S(X.finalContent)??"",H=Y.length>120?Y.slice(0,120)+"…":Y;return{title:this.pushTitleForConversation(Q),body:H||"You have a new message.",data:{conversationId:Q}}}return null}ensureFileReceiver(){if(!this._fileReceiver)this._fileReceiver=new Y1((Z,$)=>{this.sendWire(Z,$)});return this._fileReceiver}closePeerConnection(){if(this.answerGatherTimer)clearTimeout(this.answerGatherTimer),this.answerGatherTimer=null;this.stopHeartbeatLoop(),this.flushAllStreamBatches();try{this.dataChannel?.close?.()}catch{}try{this.peerConnection?.close?.()}catch{}this.dataChannel=null,this.peerConnection=null,this.remoteDescriptionApplied=!1,this.currentSessionId=null,this.currentOfferRequestId=null,this.pendingRemoteCandidates=[],this.awaitingStateSyncRequest=!0,this.lastSnapshotSignatureByType.clear(),this.lastSnapshotSentAtByType.clear()}cleanup(){if(this.pendingPushTimer)clearTimeout(this.pendingPushTimer),this.pendingPushTimer=null;if(this.stopSignalingHeartbeat(),this.pendingPushRequest=null,this.closePeerConnection(),this.pendingSignalQueue=[],this.streamTextByMessageId.clear(),this.pendingStreamBatches.clear(),this.lastSnapshotSignatureByType.clear(),this.lastSnapshotSentAtByType.clear(),this._fileReceiver)this._fileReceiver.dispose(),this._fileReceiver=null;if(this.signalingWs){try{this.signalingWs.close()}catch{}this.signalingWs=null}this.onSignalingStatus?.(!1),this.onDataChannelStatus?.(!1)}}var G="[botmobile:webrtc]",r4=30000,I2=1000,s4=1000,y2=10485760,u2=1000,o4=5000,n4=600,t4=50,a4=15000,e4=45000,Z5=15000,$5=45000,X5=500,Q5=256,Y5=2000,H5=1e4,z0=null,v2=!1;var g2=OZ(()=>{x2();X0();f2()});import V1 from"node:fs";import G5 from"node:os";import c2 from"node:path";function VZ(Z){if(typeof Z!=="string")return null;let $=Z.trim().toLowerCase();return $.length>0?$:null}function gZ(Z){if(typeof Z!=="string")return;let $=Z.trim();return $.length>0?$:void 0}function N0(Z){if(typeof Z!=="string")return;let $=Z.trim();return $.length>0?$:void 0}function pZ(Z){if(typeof Z==="number"&&Number.isFinite(Z)&&Z>0)return Math.floor(Z);return Date.now()}function z5(){try{V1.mkdirSync(p2,{recursive:!0})}catch(Z){console.warn(`${l2} failed creating state dir ${p2}: ${String(Z)}`)}}function _5(Z){i.version=J1,i.updatedAt=typeof Z.updatedAt==="number"&&Number.isFinite(Z.updatedAt)?Math.max(0,Math.floor(Z.updatedAt)):0,i.agents={};for(let[$,X]of Object.entries(Z.agents??{})){let Q=VZ($)??VZ(X.id),Y=gZ(X.name);if(!Q||!Y)continue;i.agents[Q]={id:Q,name:Y,emoji:N0(X.emoji),updatedAt:pZ(X.updatedAt)}}i.cronJobs={};for(let[$,X]of Object.entries(Z.cronJobs??{})){let Q=VZ($)??VZ(X.id);if(!Q)continue;let Y=VZ(X.agentId??void 0)??void 0;i.cronJobs[Q]={id:Q,name:gZ(X.name),agentId:Y,agentName:gZ(X.agentName),agentEmoji:N0(X.agentEmoji),enabled:typeof X.enabled==="boolean"?X.enabled:void 0,updatedAt:pZ(X.updatedAt),lastSeenAt:typeof X.lastSeenAt==="number"&&Number.isFinite(X.lastSeenAt)?Math.max(0,Math.floor(X.lastSeenAt)):void 0,deletedAt:typeof X.deletedAt==="number"&&Number.isFinite(X.deletedAt)?Math.max(0,Math.floor(X.deletedAt)):void 0}}}function N5(){d2=!0;try{let Z=V1.readFileSync(_0,"utf8"),$=JSON.parse(Z);if(!$||typeof $!=="object")return;if($.version!==J1)return;_5($)}catch{}}function CZ(){if(d2)return;N5()}function i2(){if(!jZ)return;if(mZ)return;mZ=setTimeout(()=>{mZ=null,r2()},W5)}function r2(){if(CZ(),!jZ)return;z5(),i.updatedAt=Date.now();try{let Z=JSON.stringify(i,null,2);V1.writeFileSync(_0,`${Z}
9
+ `,"utf8"),jZ=!1}catch(Z){console.warn(`${l2} failed writing state ${_0}: ${String(Z)}`)}}function s2(){jZ=!0,i2()}function o2(){CZ()}function n2(){if(mZ)clearTimeout(mZ),mZ=null;r2()}function t2(Z){CZ();let $=VZ(Z.id),X=gZ(Z.name);if(!$||!X)return;let Q=i.agents[$],Y={id:$,name:X,emoji:N0(Z.emoji)??Q?.emoji,updatedAt:pZ(Z.updatedAt)};if(!(!Q||Q.name!==Y.name||Q.emoji!==Y.emoji||Q.updatedAt!==Y.updatedAt))return;i.agents[$]=Y,s2()}function a2(Z){CZ();let $=VZ(Z);if(!$)return;return i.agents[$]}function E0(Z){CZ();let $=VZ(Z.id);if(!$)return;let X=i.cronJobs[$],Q={id:$,name:gZ(Z.name)??X?.name,agentId:VZ(Z.agentId)??X?.agentId,agentName:gZ(Z.agentName)??X?.agentName,agentEmoji:N0(Z.agentEmoji)??X?.agentEmoji,enabled:typeof Z.enabled==="boolean"?Z.enabled:X?.enabled,updatedAt:pZ(Z.updatedAt),lastSeenAt:Z.lastSeenAt!==void 0?pZ(Z.lastSeenAt):X?.lastSeenAt,deletedAt:Z.deletedAt!==void 0?pZ(Z.deletedAt):X?.deletedAt};if(!(!X||X.name!==Q.name||X.agentId!==Q.agentId||X.agentName!==Q.agentName||X.agentEmoji!==Q.agentEmoji||X.enabled!==Q.enabled||X.updatedAt!==Q.updatedAt||X.lastSeenAt!==Q.lastSeenAt||X.deletedAt!==Q.deletedAt))return;i.cronJobs[$]=Q,s2()}function q1(Z){CZ();let $=VZ(Z);if(!$)return;return i.cronJobs[$]}function O1(Z){CZ();let $=Date.now(),X=new Set;for(let Q of Z){let Y=VZ(Q);if(!Y)continue;X.add(Y);let H=i.cronJobs[Y];if(!H)continue;if(H.lastSeenAt===$&&H.deletedAt===void 0)continue;H.lastSeenAt=$,H.deletedAt=void 0,H.updatedAt=Math.max(H.updatedAt,$),jZ=!0}for(let[Q,Y]of Object.entries(i.cronJobs)){if(X.has(Q))continue;if(Y.deletedAt)continue;Y.deletedAt=$,Y.updatedAt=Math.max(Y.updatedAt,$),jZ=!0}if(jZ)i2()}var l2="[botmobile:cache]",J1=1,W5=1000,_0,p2,d2=!1,jZ=!1,mZ=null,i;var e2=OZ(()=>{_0=c2.join(G5.homedir(),".openclaw","botmobile","state.json"),p2=c2.dirname(_0),i={version:J1,updatedAt:0,agents:{},cronJobs:{}}});var _3={};b3(_3,{wsRelay:()=>k,monitorBotMobileProvider:()=>z3,handleToolHookEvent:()=>C0,handleAgentRunHookEnd:()=>C1,getFileWatcherCount:()=>W6,bindSessionToConversation:()=>M1});import E5 from"node:dns";import{watch as K1,statSync as w0,readFileSync as j1}from"node:fs";import UZ from"node:path";import rZ from"node:os";import{createReplyPrefixOptions as P5}from"openclaw/plugin-sdk";function k(Z,$){if($?.record!==!1)J2(Z);if(LZ)LZ.sendLegacyEnvelope(Z);return!0}function b5(Z,$){return SZ(Z,$).name}function f5(Z,$){return SZ(Z,$).emoji}function SZ(Z,$){let X=fZ(Z,$),Q=a2($),Y=X.name;if((X.source==="agent-id"||!Y||Y===$)&&Q?.name)Y=Q.name;let H=X.emoji??Q?.emoji;return t2({id:$,name:Y,emoji:H,updatedAt:Date.now()}),{name:Y,emoji:H}}function q3(Z){return{resolveAgentDisplay:({agentId:$})=>SZ(Z,$),resolveCronSnapshot:($)=>{let X=q1($);if(!X)return;return{name:X.name,agentId:X.agentId,agentName:X.agentName,agentEmoji:X.agentEmoji}}}}function cZ(Z){if(!Array.isArray(Z))return;return Z.map((X)=>typeof X==="string"?X.trim():"").filter((X)=>X.length>0)}function I5(Z){let $=new Set,X=[];for(let Q of Z){let Y=Q.trim();if(!Y)continue;if($.has(Y))continue;$.add(Y),X.push(Y)}return X.length>0?X:void 0}function y5(Z){if(!Z)return{};let $=Z.trim();if(!$)return{};let X=$.indexOf("/");if(X<0)return{model:$};let Q=$.slice(0,X).trim(),Y=$.slice(X+1).trim();return{provider:Q||void 0,model:Y||void 0}}function u5(Z){let $=Z?.trim().toLowerCase();if(!$)return;switch($){case"anthropic":return"ANTHROPIC_API_KEY";case"openai":return"OPENAI_API_KEY";case"gemini":case"google":return"GEMINI_API_KEY";case"openrouter":return"OPENROUTER_API_KEY";case"xai":return"XAI_API_KEY";case"groq":return"GROQ_API_KEY";case"perplexity":return"PERPLEXITY_API_KEY";case"deepseek":return"DEEPSEEK_API_KEY";case"mistral":return"MISTRAL_API_KEY";case"cohere":return"COHERE_API_KEY";default:return}}function y(Z){let $=Z.replace(/\s+/g," ").trim();if(!$)return"working";if($.length<=Z3)return $;return`${$.slice(0,Z3-3).trimEnd()}...`}function j0(Z){if(!Z)return;let $=Z.trim();return $.length>0?$:void 0}function P1(Z){if(!Z)return;let $=Z.trim();return $.length>0?$:void 0}function v5(Z){let $=Z.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[._-]+/g," ").replace(/\s+/g," ").trim().toLowerCase();if(!$)return"running tool";return y(`running ${$}`)}function o(Z){if(!Z)return;let $=Z.replace(/\s+/g," ").trim();if(!$)return;if($.length<=X3)return $;return`${$.slice(0,X3-1).trimEnd()}…`}function e(Z,$){if(!Z)return;for(let X of $){let Q=Z[X];if(typeof Q==="string"&&Q.trim().length>0)return Q.trim()}return}function m5(Z){if(!Z)return;let $=Z.trim().split(/\s+/)[0];if(!$)return;if($.startsWith("/")){let X=$.split("/");return X[X.length-1]||$}return $}function g5(Z){if(!Z)return;try{let $=new URL(Z).hostname;return $?o($):void 0}catch{return o(Z)}}function p5(Z){let $=e(Z,["action","op","operation","method"]);return o($)}function $Z(Z,$){if(!$)return y(Z);return y(`${Z} (${$})`)}function c5(Z,$){let X=Z.trim().toLowerCase(),Q=p5($);if(X==="web_search"){let Y=o(e($,["query","q","text"]));return $Z("searching the web",Y)}if(X==="web_fetch"){let Y=g5(e($,["url"]));return $Z("fetching webpage",Y)}if(X==="browser"){let Y=o(e($,["url","selector","query","text"]));if(Q&&Y)return y(`browser ${Q} (${Y})`);if(Q)return y(`browser ${Q}`);return $Z("using browser tool",Y)}if(X==="memory_search"){let Y=o(e($,["query","q","text"]));return $Z("searching memory",Y)}if(X==="memory_get"){let Y=o(e($,["id","key","name"]));return $Z("reading memory entry",Y)}if(X==="sessions_history"){let Y=o(e($,["sessionId","sessionKey","id"]));return $Z("reading session history",Y)}if(X==="sessions_list")return y("listing sessions");if(X==="sessions_send"){let Y=o(e($,["sessionId","sessionKey","to","target"]));return $Z("sending cross-session message",Y)}if(X==="sessions_spawn"){let Y=o(e($,["name","label","agentId"]));return $Z("starting helper session",Y)}if(X==="cron"){if(Q)return y(`updating scheduled task (${Q})`);return y("updating scheduled task")}if(X==="message"){if(Q)return y(`preparing message action (${Q})`);return y("preparing message")}if(X==="gateway"){if(Q)return y(`checking gateway (${Q})`);return y("checking gateway")}if(X==="canvas"){if(Q)return y(`updating canvas (${Q})`);return y("updating canvas")}if(X==="nodes"){if(Q)return y(`running node action (${Q})`);return y("running node action")}if(X==="image"){if(Q)return y(`working with image (${Q})`);return y("working with image")}if(X==="tts")return y("generating audio");if(X==="exec_command"){let Y=e($,["cmd","command"]),H=o(m5(Y));return $Z("running terminal command",H)}if(X==="write_stdin")return y("continuing terminal command");if(X==="search_query"){let Y=o(e($,["q","query"]));return $Z("searching",Y)}if(X==="open"){let Y=o(e($,["ref_id","refId","url"]));return $Z("opening reference",Y)}if(X==="click")return y("opening linked reference");if(X==="find"){let Y=o(e($,["pattern","text"]));return $Z("finding text",Y)}if(X==="apply_patch")return y("editing code");return v5(Z)}function O3(Z,$){return`${Z}::${$??"__unknown__"}`}function l5(Z=Date.now()){for(let[$,X]of sZ)if(Z-X.updatedAt>C5)sZ.delete($)}function d5(Z){let $=j0(Z);if(!$)return;let X=sZ.get($);if(X)return X.updatedAt=Date.now(),X.conversationId;let Q=$.match(x5);if(Q&&Q[1]?.trim())return R(Q[1]);let Y=$.match(T5);if(Y&&Y[1]?.trim())return R(Y[1]);let H=$.match(h5);if(H&&H[1]?.trim())return`cron:${H[1].trim().toLowerCase()}`;return}function R1(Z){let $,X=-1,Q=`${Z}::`;for(let[Y,H]of JZ){if(!Y.startsWith(Q))continue;if(H.tools.length===0)continue;if(H.updatedAt>X)X=H.updatedAt,$=Y}if($)return DZ.set(Z,$),$;DZ.delete(Z);return}function i5(Z,$){if($){let Q=O3(Z,$);if(JZ.delete(Q),DZ.get(Z)===Q)R1(Z);return}let X=`${Z}::`;for(let Q of Array.from(JZ.keys())){if(!Q.startsWith(X))continue;JZ.delete(Q)}DZ.delete(Z)}function M1(Z){let $=j0(Z.sessionKey);if(!$)return;let X=R(Z.conversationId);if(!X)return;l5(),sZ.set($,{conversationId:X,updatedAt:Date.now()})}function C0(Z){let $=P1(Z.agentId),X=P1(Z.toolName);if(!$||!X)return;let Q=Date.now(),Y=j0(Z.sessionKey),H=O3($,Y),V=d5(Y),J=MZ.get($)?.status,q=JZ.get(H)??{agentId:$,sessionKey:Y,conversationId:V,tools:[],updatedAt:Q};if(q.updatedAt=Q,V)q.conversationId=V;if(Z.phase==="start"){let D=c5(X,Z.toolParams);if(q.tools.push({name:X,activity:D}),JZ.set(H,q),DZ.set($,H),J!=="working")AZ.add($);kZ($,"working",{activeConversationId:V,activeTool:D},Z.config),console.log(`${$3} before_tool_call agent=${$} tool=${X} activity="${D}" session=${Y??"-"} conv=${V??"-"} depth=${q.tools.length}`);return}let O=!1;for(let D=q.tools.length-1;D>=0;D-=1){if(q.tools[D]?.name!==X)continue;q.tools.splice(D,1),O=!0;break}if(!O&&q.tools.length>0)q.tools.pop();if(q.tools.length===0){if(JZ.delete(H),DZ.get($)===H)R1($)}else JZ.set(H,q),DZ.set($,H);let B=DZ.get($)??R1($),K=B?JZ.get(B):void 0,L=K?.tools[K.tools.length-1];if(L)kZ($,"working",{activeConversationId:K?.conversationId,activeTool:L.activity},Z.config);else if(AZ.has($))AZ.delete($),kZ($,"idle",{activeTool:void 0,activeConversationId:void 0},Z.config);else kZ($,"working",{activeTool:_1,activeConversationId:K?.conversationId},Z.config);console.log(`${$3} after_tool_call agent=${$} tool=${X} session=${Y??"-"} conv=${V??"-"} depth=${q.tools.length} next="${L?.activity??_1}" error=${Z.error?"yes":"no"}`)}function C1(Z){let $=P1(Z.agentId);if(!$)return;let X=j0(Z.sessionKey);if(i5($,X),!AZ.has($))return;AZ.delete($),kZ($,"idle",{activeConversationId:void 0,activeTool:void 0,errorMessage:Z.success===!1?Z.error:void 0},Z.config)}function r5(Z){let $=["token","apiKey","key","accessToken","refreshToken","secret"];for(let X of $){let Q=Z[X];if(typeof Q==="string"&&Q.trim().length>0)return!0}return!1}function s5(Z,$){let X=$?.trim().toLowerCase();if(!X)return!1;let Q=UZ.join(rZ.homedir(),".openclaw","agents",Z,"agent","auth-profiles.json");try{let Y=w0(Q),H=F1.get(Z);if(H&&H.mtimeMs===Y.mtimeMs&&H.size===Y.size)return H.hasCredentialByProvider[X]===!0;let V=j1(Q,"utf8"),q=JSON.parse(V)?.profiles,O={};if(q&&typeof q==="object")for(let B of Object.values(q)){if(!B||typeof B!=="object")continue;let K=B,L=g(K.provider)?.toLowerCase();if(!L)continue;if(r5(K))O[L]=!0;else if(O[L]!==!0)O[L]=!1}return F1.set(Z,{mtimeMs:Y.mtimeMs,size:Y.size,hasCredentialByProvider:O}),O[X]===!0}catch{return F1.delete(Z),!1}}function o5(Z,$){let X=u5(Z),Q=s5($,Z);if(!X&&!Q)return{};return{envName:X,present:Q}}function K3(Z,$){let X=Z.agents,Q=X&&typeof X.defaults==="object"&&X.defaults?X.defaults:{},H=(Array.isArray(X?.list)?X.list:[]).find((d)=>typeof d?.id==="string"&&d.id===$)??{},V=typeof H.model==="string"?H.model:typeof H.model?.primary==="string"?H.model.primary:typeof Q.model?.primary==="string"?Q.model.primary:void 0,J=typeof V==="string"?V.trim():"",q=y5(J),O=typeof H.workspace==="string"?H.workspace:typeof Q.workspace==="string"?Q.workspace:void 0,B=typeof O==="string"&&O.trim().length>0?O.trim():void 0,K=F3($),L=cZ(H.skills)??cZ(Q.skills)??K?.skills,D=cZ(H.tools?.allow)??cZ(Q.tools?.allow),U=cZ(H.tools?.deny)??cZ(Q.tools?.deny),_=typeof H.contextTokens==="number"?H.contextTokens:Q.contextTokens,N=typeof _==="number"&&Number.isFinite(_)?Math.max(0,Math.floor(_)):K?.contextTokens,W=typeof H.timeoutSeconds==="number"?H.timeoutSeconds:Q.timeoutSeconds,h=typeof W==="number"&&Number.isFinite(W)?Math.max(0,Math.floor(W)):void 0,A=typeof H.maxConcurrent==="number"?H.maxConcurrent:Q.maxConcurrent,p=typeof A==="number"&&Number.isFinite(A)?Math.max(0,Math.floor(A)):void 0,b=typeof H.typingMode==="string"?H.typingMode:Q.typingMode,w=typeof b==="string"&&b.trim().length>0?b.trim():void 0,c=q.provider??K?.modelProvider,j=q.model??K?.model,E=B??K?.promptWorkspace,v=typeof N==="number"&&typeof K?.totalTokens==="number"?Math.max(0,N-Math.max(0,Math.floor(K.totalTokens))):void 0,z=typeof N==="number"&&N>0&&typeof K?.totalTokens==="number"?Math.min(1,Math.max(0,K.totalTokens/N)):void 0,m=o5(c,$),x=X6($,K),l={model:j,provider:c,workspace:E,skills:L,skillDetails:K?.skillDetails,toolsAllow:D,toolsDeny:U,contextTokens:N,contextRemainingTokens:v,contextUsageRatio:z,timeoutSeconds:h,maxConcurrent:p,typingMode:w,sessionId:K?.sessionId,sessionUpdatedAt:K?.updatedAt,sessionInputTokens:K?.inputTokens,sessionOutputTokens:K?.outputTokens,sessionTotalTokens:K?.totalTokens,usageEventCount:x?.usageEventCount,usageInputTokens:x?.usageInputTokens,usageOutputTokens:x?.usageOutputTokens,usageCacheReadTokens:x?.usageCacheReadTokens,usageCacheWriteTokens:x?.usageCacheWriteTokens,usageTotalTokens:x?.usageTotalTokens,usageTotalCostUsd:x?.usageTotalCostUsd,usageUpdatedAt:x?.usageUpdatedAt,historySessionCount:K?.historySessionCount,historyInputTokens:K?.historyInputTokens,historyOutputTokens:K?.historyOutputTokens,historyTotalTokens:K?.historyTotalTokens,historyUpdatedAt:K?.historyUpdatedAt,promptSource:K?.promptSource,promptGeneratedAt:K?.promptGeneratedAt,providerKeyEnv:m.envName,providerKeyPresent:m.present},n=B3(l);return l.accountStatus=n.status,l.accountStatusReason=n.reason,Object.values(l).some((d)=>d!==void 0)?l:void 0}function B3(Z){if(Z.providerKeyPresent===!1)return{status:"missing_credentials",reason:Z.providerKeyEnv?`No provider credentials detected (${Z.providerKeyEnv} not set)`:"No provider credentials detected"};if(Z.providerKeyPresent===!0)return{status:"ready",reason:"Provider credentials detected"};return{status:"unknown",reason:Z.provider?"Provider configured":"Provider unknown"}}function L3(Z,$,X){if(!Z&&$!=="error")return Z;let Q={...Z??{}};if($==="error")Q.accountStatus="error",Q.accountStatusReason=g(X)??Q.accountStatusReason??"Agent runtime error";else{let H=B3(Q);Q.accountStatus=H.status,Q.accountStatusReason=H.reason}return Object.values(Q).some((H)=>H!==void 0)?Q:void 0}function C(Z){if(typeof Z!=="number"||!Number.isFinite(Z))return;return Z}function n5(Z){return typeof Z==="boolean"?Z:void 0}function g(Z){if(typeof Z!=="string")return;let $=Z.trim();return $.length>0?$:void 0}function t5(Z){if(!Z||typeof Z!=="object")return;let $=Z,X=g($.name);if(!X)return;return{name:X,description:g($.description),source:g($.source),filePath:g($.filePath),baseDir:g($.baseDir),disableModelInvocation:n5($.disableModelInvocation)}}function D3(){return{eventCount:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,totalTokens:0,totalCostUsd:0,updatedAt:0}}function a5(Z){return{eventCount:Math.max(0,Math.floor(Z?.usageEventCount??0)),inputTokens:Math.max(0,Math.floor(Z?.usageInputTokens??0)),outputTokens:Math.max(0,Math.floor(Z?.usageOutputTokens??0)),cacheReadTokens:Math.max(0,Math.floor(Z?.usageCacheReadTokens??0)),cacheWriteTokens:Math.max(0,Math.floor(Z?.usageCacheWriteTokens??0)),totalTokens:Math.max(0,Math.floor(Z?.usageTotalTokens??0)),totalCostUsd:Math.max(0,C(Z?.usageTotalCostUsd)??0),updatedAt:Math.max(0,Math.floor(Z?.usageUpdatedAt??0))}}function U3(Z){if(Z.eventCount<=0)return;return{usageEventCount:Z.eventCount,usageInputTokens:Z.inputTokens,usageOutputTokens:Z.outputTokens,usageCacheReadTokens:Z.cacheReadTokens,usageCacheWriteTokens:Z.cacheWriteTokens,usageTotalTokens:Z.totalTokens,usageTotalCostUsd:Number(Z.totalCostUsd.toFixed(6)),usageUpdatedAt:Z.updatedAt>0?Z.updatedAt:void 0}}function S1(Z){if(typeof Z==="number"&&Number.isFinite(Z)&&Z>0){if(Z>=1000000000000)return Math.floor(Z);if(Z>=1e9)return Math.floor(Z*1000);return Math.floor(Z)}if(typeof Z==="string"&&Z.trim().length>0){let $=Number(Z);if(Number.isFinite($)&&$>0)return S1($);let X=Date.parse(Z);if(Number.isFinite(X)&&X>0)return Math.floor(X)}return 0}function e5(Z){if(!Z.includes('"usage"'))return;try{let $=JSON.parse(Z),X=$.message;if(!X||typeof X!=="object")return;let Q=X.usage;if(!Q||typeof Q!=="object")return;let Y=Q,H=Math.max(0,Math.floor(C(Y.input)??C(Y.inputTokens)??C(Y.input_tokens)??0)),V=Math.max(0,Math.floor(C(Y.output)??C(Y.outputTokens)??C(Y.output_tokens)??0)),J=Math.max(0,Math.floor(C(Y.cacheRead)??C(Y.cacheReadTokens)??C(Y.cache_read_tokens)??0)),q=Math.max(0,Math.floor(C(Y.cacheWrite)??C(Y.cacheWriteTokens)??C(Y.cache_write_tokens)??0)),O=H+V+J+q,B=Math.max(0,Math.floor(C(Y.totalTokens)??C(Y.total_tokens)??O)),K=Y.cost,L=K&&typeof K==="object"?K:void 0,D=Math.max(0,C(Y.totalCostUsd)??C(Y.total_cost_usd)??C(L?.total)??0),U=Math.max(S1(X.timestamp),S1($.timestamp));return{eventCount:1,inputTokens:H,outputTokens:V,cacheReadTokens:J,cacheWriteTokens:q,totalTokens:B,totalCostUsd:D,updatedAt:U}}catch{return}}function Z6(Z,$){if(UZ.isAbsolute($))return $;return UZ.join(rZ.homedir(),".openclaw","agents",Z,"sessions",$)}function $6(Z){try{let $=w0(Z),X=U1.get(Z);if(X&&X.mtimeMs===$.mtimeMs&&X.size===$.size)return X.totals;let Q=j1(Z,"utf8"),Y=D3(),H=Q.split(/\r?\n/);for(let J of H){let q=J.trim();if(!q)continue;let O=e5(q);if(!O)continue;Y.eventCount+=O.eventCount,Y.inputTokens+=O.inputTokens,Y.outputTokens+=O.outputTokens,Y.cacheReadTokens+=O.cacheReadTokens,Y.cacheWriteTokens+=O.cacheWriteTokens,Y.totalTokens+=O.totalTokens,Y.totalCostUsd+=O.totalCostUsd,Y.updatedAt=Math.max(Y.updatedAt,O.updatedAt)}let V=U3(Y);return U1.set(Z,{mtimeMs:$.mtimeMs,size:$.size,totals:V}),V}catch{U1.delete(Z);return}}function X6(Z,$){let X=Date.now(),Q=D1.get(Z);if(Q&&X-Q.refreshedAt<j5)return Q.totals;let Y=$?.sessionFiles??[];if(Y.length===0){D1.set(Z,{refreshedAt:X,totals:void 0});return}let H=D3(),V=new Set;for(let q of Y){let O=q.trim();if(!O||V.has(O))continue;V.add(O);let B=Z6(Z,O),K=$6(B);if(!K)continue;let L=a5(K);H.eventCount+=L.eventCount,H.inputTokens+=L.inputTokens,H.outputTokens+=L.outputTokens,H.cacheReadTokens+=L.cacheReadTokens,H.cacheWriteTokens+=L.cacheWriteTokens,H.totalTokens+=L.totalTokens,H.totalCostUsd+=L.totalCostUsd,H.updatedAt=Math.max(H.updatedAt,L.updatedAt)}let J=U3(H);return D1.set(Z,{refreshedAt:X,totals:J}),J}function F3(Z){let $=UZ.join(rZ.homedir(),".openclaw","agents",Z,"sessions","sessions.json");try{let X=w0($),Q=lZ.get(Z);if(Q&&Q.mtimeMs===X.mtimeMs&&Q.size===X.size)return Q.summary;let Y=j1($,"utf8"),H=JSON.parse(Y);if(!H||typeof H!=="object"){lZ.set(Z,{mtimeMs:X.mtimeMs,size:X.size,summary:void 0});return}let V,J,q=0,O=`agent:${Z}:`,B=0,K=0,L=0,D=0,U=0,_=new Set;for(let[E,v]of Object.entries(H)){if(!E.startsWith(O))continue;if(!v||typeof v!=="object")continue;let z=v,m=g(z.sessionFile);if(m)_.add(m);let x=C(z.updatedAt)??0;if(B+=1,U=Math.max(U,x),K+=Math.max(0,C(z.inputTokens)??0),L+=Math.max(0,C(z.outputTokens)??0),D+=Math.max(0,C(z.totalTokens)??0),!J||x>=q)V=E,J=z,q=x}if(!J){lZ.set(Z,{mtimeMs:X.mtimeMs,size:X.size,summary:void 0});return}let N=J.skillsSnapshot,h=(Array.isArray(N?.skills)?N?.skills:[]).map((E)=>{if(typeof E==="string")return g(E);if(!E||typeof E!=="object")return;return g(E.name)}).filter((E)=>typeof E==="string"),p=(Array.isArray(N?.resolvedSkills)?N.resolvedSkills:[]).map((E)=>t5(E)).filter((E)=>!!E),b=p.map((E)=>E.name),w=I5([...h,...b]),c=J.systemPromptReport,j={sessionKey:V,sessionId:g(J.sessionId),updatedAt:C(J.updatedAt),modelProvider:g(J.modelProvider),model:g(J.model),contextTokens:C(J.contextTokens),inputTokens:C(J.inputTokens),outputTokens:C(J.outputTokens),totalTokens:C(J.totalTokens),skillsCount:w?.length,skills:w,skillDetails:p.length>0?p:void 0,historySessionCount:B>0?B:void 0,historyInputTokens:K>0?K:void 0,historyOutputTokens:L>0?L:void 0,historyTotalTokens:D>0?D:void 0,historyUpdatedAt:U>0?U:void 0,promptSource:g(c?.source),promptGeneratedAt:C(c?.generatedAt),promptWorkspace:g(c?.workspaceDir),sessionFiles:_.size>0?Array.from(_):void 0};return lZ.set(Z,{mtimeMs:X.mtimeMs,size:X.size,summary:j}),j}catch{lZ.delete(Z);return}}function Q6(Z,$,X){let Q=SZ(Z,$),Y=F3($),H=Y?{...Y,sessionFileCount:Y.sessionFiles?.length,sessionFiles:void 0}:null,V={agentId:$,display:Q,configDetails:X??null,sessionSummary:H},J=JSON.stringify(V);if(E1.get($)===J)return;E1.set($,J),console.log(`${u} [agent-details] ${JSON.stringify(V,null,2)}`)}function Y6(Z,$){if(!$)return Z;if(Z.startsWith($))return Z;return`${$} ${Z}`.trim()}function H6(Z,$){let X=g(Z);if(X)return X.slice(0,96);return(($.split(/\r?\n/,1)[0]?.trim()??"")||"Agent Task").slice(0,96)}function V6(Z){if(typeof Z!=="number"||!Number.isFinite(Z))return 3600000;return Math.max(60000,Math.min(2592000000,Math.floor(Z)))}function P0(Z){if(!Z)return;let $=Z.trim();if(!$)return;if($.startsWith("conversation:"))return;if($.toLowerCase()==="conversation")return;return R($)}function J6(Z){let $=Z.agents?.list;if(!Array.isArray($))return new Set;let X=new Set;for(let Q of $){if(!Q||typeof Q!=="object")continue;let Y=typeof Q.id==="string"?Q.id.trim():"";if(!Y)continue;X.add(Y)}return X}function G3(Z,$){if(!$)return;let X=$.trim();if(!X)return;if(X.startsWith("conversation:"))return;if(X.toLowerCase()==="conversation")return;if(X.includes(":"))return;let Q=J6(Z);if(Q.size>0&&!Q.has(X))return;return X}function Y3(Z,$){let X=Z.split(":");if(X.length<2||X[0]!=="agent")return Z;return X[1]=$,X.join(":")}function H3(Z){let $=Z.trim();if(!$)return 0;return Math.max(1,Math.ceil($.length/4))}function q6(Z){if(Z==="error")return"error";if(Z==="skipped")return"skipped";return"ok"}function V3(Z,$){return`${Z}:${$??Date.now()}`}function O6(Z){let $=Z.agents?.list??[];if(!Array.isArray($))return[];let X=new Set,Q=Date.now(),Y=[];for(let H of $){let V=H?.id??"unknown";X.add(V);let J=dZ.get(V),q=MZ.get(V),O=SZ(Z,V),B=K3(Z,V)??q?.details,K=q?.status??"idle",L={agentId:V,name:O.name,emoji:O.emoji??q?.emoji,color:q?.color,details:L3(B,K,q?.errorMessage),status:K,activeConversationId:P0(q?.activeConversationId),activeTool:q?.activeTool,activeElapsedMs:q?.activeElapsedMs,activeTokens:q?.activeTokens,sessionTokensIn:J?.in??q?.sessionTokensIn??0,sessionTokensOut:J?.out??q?.sessionTokensOut??0,lastActivityAt:q?.lastActivityAt??Q,errorMessage:q?.errorMessage};MZ.set(V,L),Q6(Z,V,L.details),Y.push(L)}for(let H of Array.from(MZ.keys()))if(!X.has(H))MZ.delete(H);return Y}function k0(Z){return O6(Z)}function kZ(Z,$,X,Q){let Y=!!X&&Object.prototype.hasOwnProperty.call(X,"activeConversationId"),H=!!X&&Object.prototype.hasOwnProperty.call(X,"activeTool"),V=!!X&&Object.prototype.hasOwnProperty.call(X,"activeTokens"),J=MZ.get(Z),q=dZ.get(Z),O=Date.now(),B=J?.name??(Q?b5(Q,Z):Z||"Assistant"),K=J?.emoji??(Q?f5(Q,Z):void 0),L=J?.details??(Q?K3(Q,Z):void 0),D=X?.errorMessage??J?.errorMessage,U={agentId:Z,name:B,emoji:K,color:J?.color,details:L3(L,$,D),status:$,activeConversationId:Y?P0(X?.activeConversationId):P0(J?.activeConversationId),activeTool:H?X?.activeTool:J?.activeTool,activeElapsedMs:X?.activeElapsedMs,activeTokens:V?X?.activeTokens:J?.activeTokens,sessionTokensIn:q?.in??J?.sessionTokensIn??0,sessionTokensOut:q?.out??J?.sessionTokensOut??0,lastActivityAt:O,errorMessage:X?.errorMessage};if($==="working"){if(!U.activeConversationId)U.activeConversationId=P0(J?.activeConversationId);if(!H&&!U.activeTool)U.activeTool=J?.activeTool;if(!V&&U.activeTokens===void 0)U.activeTokens=J?.activeTokens}else U.activeConversationId=void 0,U.activeTool=void 0,U.activeTokens=void 0;if($!=="error"&&X?.errorMessage===void 0)U.errorMessage=void 0;MZ.set(Z,U),k({type:"agent_status",agentId:U.agentId,status:U.status,color:U.color,details:U.details,activeConversationId:U.activeConversationId,activeTool:U.activeTool,activeElapsedMs:U.activeElapsedMs,activeTokens:U.activeTokens,sessionTokensIn:U.sessionTokensIn,sessionTokensOut:U.sessionTokensOut,lastActivityAt:U.lastActivityAt,errorMessage:U.errorMessage})}function K6(Z){if(Z&&typeof Z==="object"){let $=Z;if($.kind==="at"&&typeof $.at==="string")return{kind:"at",at:$.at};if($.kind==="every"&&typeof $.everyMs==="number")return{kind:"every",everyMs:Math.max(1,Math.floor($.everyMs))};if($.kind==="cron"&&typeof $.expr==="string")return{kind:"cron",expr:$.expr,tz:typeof $.tz==="string"?$.tz:void 0}}return{kind:"every",everyMs:60000}}function W3(Z,$){return Z.map((X)=>{let Q=typeof X.agentId==="string"&&X.agentId.trim()?X.agentId:void 0,Y=Q?SZ($,Q):void 0,H=X.sessionTarget==="isolated"?"isolated":"main",V=X.payload?.kind==="agentTurn"?"agentTurn":"systemEvent",J={id:X.id,agentId:Q,agentName:Y?.name,agentEmoji:Y?.emoji,name:X.name??X.id,enabled:X.enabled!==!1,schedule:K6(X.schedule),sessionTarget:H,payloadKind:V,lastRunAt:X.state?.lastRunAtMs,lastRunStatus:X.state?.lastStatus,lastRunDurationMs:X.state?.lastDurationMs,lastRunSummary:void 0,nextRunAt:X.state?.nextRunAtMs,isRunning:!!X.state?.runningAtMs,runningElapsedMs:X.state?.runningAtMs?Date.now()-X.state.runningAtMs:void 0,runningTokens:void 0};return E0({id:J.id,name:J.name,agentId:J.agentId,agentName:J.agentName,agentEmoji:J.agentEmoji,enabled:J.enabled,updatedAt:Date.now(),lastSeenAt:Date.now(),deletedAt:void 0}),J})}function RZ(Z,$={}){let X=Date.now(),Q=$.includeDisabled??!0,Y=$.force===!0,H=p0(Z),V=Q?H:H.filter((O)=>O.enabled!==!1),J=W3(V,Z),q=JSON.stringify(J.map((O)=>({id:O.id,agentId:O.agentId,name:O.name,enabled:O.enabled,schedule:O.schedule,sessionTarget:O.sessionTarget,payloadKind:O.payloadKind,lastRunAt:O.lastRunAt,lastRunStatus:O.lastRunStatus,isRunning:O.isRunning,runningTokens:O.runningTokens})));if(q===Q3){if(!Y)return;if(X-L1<A5)return}if(!Y){if(X-L1<k5)return}Q3=q,L1=X,O1(J.map((O)=>O.id)),k({type:"cron_list",jobs:J})}function B6(Z){let $=p0(Z),X=W3($,Z);return O1(X.map((Q)=>Q.id)),{jobs:X}}function J3(Z,$){let X=typeof $?.sinceTimestampMs==="number"&&Number.isFinite($.sinceTimestampMs)?$.sinceTimestampMs:void 0,Q=typeof $?.stateBornAt==="number"&&Number.isFinite($.stateBornAt)?$.stateBornAt:void 0,Y=typeof $?.globalRevision==="number"&&Number.isFinite($.globalRevision)?$.globalRevision:void 0,H=n0({sinceTimestampMs:X,stateBornAt:Q,globalRevision:Y,conversations:$?.conversations,fallbackAgents:k0(Z),fallbackCronJobs:B6(Z).jobs});if(H.mode==="snapshot"){k({type:"state_snapshot",state:H.state},{record:!1});return}k({type:"state_delta",state:H.state,sinceTimestampMs:X},{record:!1})}function L6(Z,$){if($.action==="started")k({type:"cron_run_started",jobId:$.jobId,runId:V3($.jobId,$.runAtMs)});else if($.action==="finished")k({type:"cron_run_finished",jobId:$.jobId,runId:V3($.jobId,$.runAtMs),status:q6($.status),durationMs:$.durationMs??0,summary:$.summary,error:$.error});RZ(Z,{includeDisabled:!0})}function D6(Z){if(H0)return;H0=l1(Z,($)=>{L6(Z,$)})}function U6(){if(H0)H0(),H0=null}async function F6(Z){let{envelope:$,accountId:X,config:Q,core:Y,logger:H}=Z,V=Q,J=R($.conversationId);V2({...$,conversationId:J});let q=Y.channel.routing.resolveAgentRoute({cfg:V,channel:"botmobile",accountId:X,peer:{kind:"dm",id:J}}),O=G3(V,$.agentId);if($.agentId&&!O)H.info(`${u} ignoring invalid agent override "${$.agentId}" for conv=${J}`);if(O&&O!==q.agentId)q={...q,agentId:O,sessionKey:Y3(q.sessionKey,O),mainSessionKey:Y3(q.mainSessionKey,O)};M1({sessionKey:q.sessionKey,conversationId:J}),M1({sessionKey:q.mainSessionKey,conversationId:J});let B=SZ(V,q.agentId);F0(J,{id:q.agentId,name:B.name,emoji:B.emoji},$.timestamp);let K=Y6(B.name,B.emoji);if(N1.get(J)!==K)N1.set(J,K),k({type:"conversation_list",conversations:[{id:J,name:K,createdAt:$.timestamp,lastActivity:$.timestamp}]});let D=[];if($.pendingAttachments&&LZ?.fileReceiver)for(let P of $.pendingAttachments){let f=LZ.fileReceiver.getFilePath(P.transferId);if(f)D.push({fileName:P.fileName,mimeType:P.mimeType,filePath:f});else H.error(`${u} attachment ${P.transferId} (${P.fileName}) not found on disk`)}let U=$.body;if(D.length>0){let P=D.map((f)=>`[Attached: ${f.fileName} — file://${f.filePath}]`);U=U?`${U}
10
10
  ${P.join(`
11
11
  `)}`:P.join(`
12
- `)}let z=Q5(U);if(z>0){let P=lZ.get(q.agentId)??{in:0,out:0};P.in+=z,lZ.set(q.agentId,P)}let N=Y.channel.reply.formatAgentEnvelope({channel:"BotMobile",from:`user:${$.from}`,timestamp:$.timestamp,envelope:Y.channel.reply.resolveEnvelopeFormatOptions(V),body:U}),G=Y.channel.reply.finalizeInboundContext({Body:N,RawBody:$.body,CommandBody:$.body,From:`botmobile:user:${J}`,To:"botmobile:bot:default",SessionKey:q.sessionKey,AccountId:q.accountId,ChatType:"direct",ConversationLabel:J,SenderName:"User",SenderId:J,Provider:"botmobile",Surface:"botmobile",MessageSid:$.id,OriginatingChannel:"botmobile",OriginatingTo:"botmobile:bot:default"}),T=Y.channel.session.resolveStorePath(V.session?.store,{agentId:q.agentId});await Y.channel.session.recordInboundSession({storePath:T,sessionKey:G.SessionKey??q.sessionKey,ctx:G,updateLastRoute:{sessionKey:q.mainSessionKey,channel:"botmobile",to:`botmobile:user:${J}`,accountId:q.accountId},onRecordError:(P)=>{H.error(`Failed updating session meta: ${String(P)}`)}});let{onModelSelected:A,...p}=z7({cfg:V,agentId:q.agentId,channel:"botmobile",accountId:Q}),b=new AbortController;w0.set(J,b);let S=(P,f)=>{k({type:"error",code:P,message:f,conversationId:J})};k({type:"composing",conversationId:J,from:"bot"});let c=Date.now();AZ(q.agentId,"working",{activeConversationId:J,activeTool:z3},V);let j=crypto.randomUUID(),E=!1,v="",W=0,m=0,x="unknown",l=0,n="",QZ="",d=null,hZ=!1,x0=null,h0=()=>{if(!QZ)return;if(l>=B3){QZ="";return}if(!E)k({type:"stream_start",conversationId:J,messageId:j}),E=!0;k({type:"stream_token",conversationId:J,messageId:j,token:QZ}),QZ="",l+=1},w5=()=>{if(d||l>=B3)return;d=setTimeout(()=>{d=null,h0()},E7)};try{await Y.channel.reply.dispatchReplyWithBufferedBlockDispatcher({ctx:G,cfg:V,dispatcherOptions:{...p,deliver:async(P)=>{let f=[];if(typeof P.text==="string"&&P.text.trim().length>0)f.push(P.text);if(typeof P.mediaUrl==="string"&&P.mediaUrl.trim().length>0)f.push(P.mediaUrl);if(Array.isArray(P.mediaUrls)){for(let T0 of P.mediaUrls)if(typeof T0==="string"&&T0.trim().length>0)f.push(T0)}let FZ=f.join(`
13
- `).trim();if(!FZ)return;n=FZ,k({type:"message",id:j,conversationId:J,from:"bot",body:FZ,timestamp:Date.now()}),hZ=!0}},replyOptions:{onModelSelected:A,onAgentRunStart:()=>{if(E)return;k({type:"stream_start",conversationId:J,messageId:j}),E=!0},onPartialReply:(P)=>{let f=P.text;if(!f)return;m+=1;let FZ="";if(f.startsWith(v)){if(FZ=f.slice(v.length),x==="unknown")x="cumulative"}else if(!v.startsWith(f)){if(FZ=f,x==="unknown")x="incremental"}if(v=f,!FZ)return;if(W+=FZ.length,l>=B3)return;if(QZ+=FZ,QZ.length>=N7){if(d)clearTimeout(d),d=null;h0()}else w5()}}})}catch(P){x0=P instanceof Error?P.message:String(P)}finally{if(d)clearTimeout(d),d=null;if(h0(),E)k({type:"stream_end",conversationId:J,messageId:j,body:n}),hZ=!0;let P=n?Q5(n):Math.max(0,Math.ceil(W/4));if(P>0){let f=lZ.get(q.agentId)??{in:0,out:0};f.out+=P,lZ.set(q.agentId,f)}AZ(q.agentId,"idle",{activeElapsedMs:Date.now()-c},V),console.log(`${u} [stream] conv=${J} msg=${j.slice(0,8)} callbacks=${m} mode=${x} streamedChars=${W} tokenEvents=${l} finalLen=${n.length}`),w0.delete(J)}if(x0){if(b.signal.aborted){S("GENERATION_STOPPED","Generation stopped.");return}S("REPLY_FAILED",x0.trim()||"Failed to generate a reply.");return}if(!hZ)S("NO_REPLY","No response generated. Please try again.")}async function D8(Z){let{envelope:$,accountId:Q,config:X,core:Y,logger:H}=Z,V=X;switch($.type){case"message":{if($.from!=="user")return;await L8({envelope:$,accountId:Q,config:X,core:Y,logger:H});return}case"stop_generation":{let J=R($.conversationId),q=w0.get(J);if(q)q.abort(),w0.delete(J);return}case"state_sync_request":{Y5(V,$);return}case"client_state":return;case"cron_list_request":{MZ(V,{includeDisabled:$.includeDisabled===!0,force:!0});return}case"cron_run":{let J=await c3(V,$.jobId);if(!J.ok)k({type:"error",code:"cron_run_failed",message:J.error??"unknown"});else MZ(V,{includeDisabled:!0});return}case"cron_toggle":{let J=await l3(V,$.jobId,$.enabled);if(!J.ok)k({type:"error",code:"cron_toggle_failed",message:J.error??"unknown"});else MZ(V,{includeDisabled:!0});return}case"cron_create_from_prompt":{let J=D5(V,$.agentId),q=g($.description);if(!J||!q){k({type:"error",code:"cron_create_invalid",message:"Agent and description are required to create a task."});return}let K=await d3(V,{name:Q8($.name,q),description:q,agentId:J,enabled:!0,schedule:{kind:"every",everyMs:X8($.everyMs)},sessionTarget:"isolated",wakeMode:"now",payload:{kind:"agentTurn",message:q}});if(!K.ok)k({type:"error",code:"cron_create_failed",message:K.error??"unknown"});else MZ(V,{includeDisabled:!0});return}case"cron_runs_request":{let J=p3(V,$.jobId,$.limit??20);k({type:"cron_runs",jobId:$.jobId,runs:J.filter((q)=>q.status).map((q)=>({ts:q.ts,status:q.status,durationMs:q.durationMs,summary:q.summary,error:q.error}))});return}case"subscribe":{let J=$.topics.includes("agents"),q=$.topics.includes("cron");if(J)k({type:"agent_list",agents:k0(V)});if(q)MZ(V,{includeDisabled:!0,force:!0});Y5(V);return}default:return}}function U8(){return dZ.length}function _3(Z,$){let Q=null;return()=>{if(Q)clearTimeout(Q);Q=setTimeout(()=>{Q=null,Z()},$),S3.push(Q)}}function G3(Z){let $=Z3(Z).map((V)=>({...V})),Q=new Set($.map((V)=>V.sessionFile)),X=new Set($.slice(0,R7).map((V)=>V.sessionFile)),Y=zZ.size===0;for(let V of $)if(!zZ.has(V.sessionFile))try{let J=S0(V.sessionFile),K=!Y||X.has(V.sessionFile)?Math.max(0,J.size-P7):J.size;zZ.set(V.sessionFile,{offset:K})}catch{zZ.set(V.sessionFile,{offset:0})}for(let V of zZ.keys())if(!Q.has(V))zZ.delete(V);let H=Date.now();for(let V of $){if(V.kind!=="cron")continue;let J=V.cronJobId;if(!J)continue;let q=q3(J),K=SZ(Z,V.agentId),B=V.cronLabel??q?.name,O=V.cronAgentId??q?.agentId??V.agentId,L=V.cronAgentName??q?.agentName??K.name,D=V.cronAgentEmoji??q?.agentEmoji??K.emoji;V.cronLabel=B??V.cronLabel,V.cronAgentId=O,V.cronAgentName=L,V.cronAgentEmoji=D,E0({id:J,name:B,agentId:O,agentName:L,agentEmoji:D,updatedAt:Math.max(V.updatedAt||0,H)}),s0({conversationId:V.conversationId,cronJobId:J,cronName:B,cronAgentId:O,cronAgentName:L,cronAgentEmoji:D},V.updatedAt||H)}k3=$,console.log(`${u} [watcher] refreshed session mappings: ${$.length} transcripts tracked`)}function W3(Z){let $=0,Q=H5(Z);for(let X of k3){let Y=zZ.get(X.sessionFile)??{offset:0},H=N4(X.sessionFile,X,Z,Y,Q);if(zZ.set(X.sessionFile,H.cursor),X.kind==="cron"&&X.cronJobId)s0({conversationId:X.conversationId,cronJobId:X.cronJobId,cronName:X.cronLabel,cronAgentId:X.cronAgentId??X.agentId,cronAgentName:X.cronAgentName,cronAgentEmoji:X.cronAgentEmoji},X.updatedAt||Date.now());for(let V of H.messages)if(H4({conversationId:V.conversationId,agent:V.agent,role:V.role,content:V.content,timestamp:V.timestamp,stableId:V.stableId}))$++}if($>0)console.log(`${u} [tailer] ingested ${$} new transcript messages`)}function F8(Z){let $=UZ.join(iZ.homedir(),".openclaw"),Q=G8(Z);try{let H=O3(Q,_3(()=>{console.log(`${u} [watcher] cron jobs.json changed, reloading`),MZ(Z,{includeDisabled:!0})},500));dZ.push(H),console.log(`${u} [watcher] watching cron: ${Q}`)}catch(H){console.warn(`${u} [watcher] failed to watch cron store: ${String(H)}`)}let X=UZ.join($,"agents");try{let H=O3(X,{recursive:!0},_3(()=>{G3(Z),W3(Z)},1500));dZ.push(H),console.log(`${u} [watcher] watching sessions: ${X}`)}catch(H){console.warn(`${u} [watcher] failed to watch agents dir: ${String(H)}`)}G3(Z),W3(Z),R0=setInterval(()=>W3(Z),5000),M0=setInterval(()=>G3(Z),60000);let Y=UZ.join($,"openclaw.json");try{let H=O3(Y,_3(()=>{console.log(`${u} [watcher] config changed, re-resolving agents`),k({type:"agent_list",agents:k0(Z)})},1000));dZ.push(H),console.log(`${u} [watcher] watching config: ${Y}`)}catch(H){console.warn(`${u} [watcher] failed to watch config: ${String(H)}`)}}function _8(){if(R0)clearInterval(R0),R0=null;if(M0)clearInterval(M0),M0=null;for(let Z of S3)clearTimeout(Z);S3=[];for(let Z of dZ)try{Z.close()}catch{}dZ.length=0,zZ.clear(),k3=[]}function G8(Z){let $=Z.cron?.store;if(typeof $==="string"&&$.trim()){let Q=$.trim();if(Q.startsWith("~"))return UZ.resolve(Q.replace("~",iZ.homedir()));return UZ.resolve(Q)}return UZ.join(iZ.homedir(),".openclaw","cron","jobs.json")}async function F5(Z){let{account:$,accountId:Q,config:X,abortSignal:Y,runtime:H}=Z,V=X,J=J0(),q={info:(O)=>H.log(O),error:(O)=>H.error(O)};if(LZ)LZ.stop(),LZ=null;let K=null,B=null;i4(),$4();try{let O=E4(V,H5(V));if(O.length>0){for(let L of O){if(L.kind!=="cron"||!L.cronJobId)continue;E0({id:L.cronJobId,name:L.cronName,agentId:L.cronAgentId,agentName:L.cronAgentName,agentEmoji:L.cronAgentEmoji,updatedAt:L.updatedAt})}Q4(O)}}catch(O){console.error(`${u} failed to load historical conversations: ${String(O)}`)}try{N3.clear(),rZ.clear(),JZ.clear(),DZ.clear(),xZ.clear(),wZ.clear(),E3.clear(),cZ.clear(),O8(V),F8(V),K=new H3({account:$,onLegacyEnvelope:(O)=>{D8({envelope:O,accountId:Q,config:X,core:J,logger:q}).catch((L)=>{q.error(`${u} inbound envelope handling failed: ${String(L)}`)})},onSignalingStatus:(O)=>{q.info(`${u} signaling ${O?"connected":"disconnected"}`)},onDataChannelStatus:(O)=>{q.info(`${u} datachannel ${O?"connected":"disconnected"}`)}}),LZ=K,B=K.run(Y).catch((O)=>{q.error(`${u} transport run failed: ${String(O)}`)}),k({type:"agent_list",agents:k0(V)}),MZ(V,{includeDisabled:!0,force:!0}),await new Promise((O)=>{if(Y.aborted){O();return}Y.addEventListener("abort",()=>O(),{once:!0})})}finally{if(K){if(K.stop(),LZ===K)LZ=null}if(B)await B;_8(),B8(),rZ.clear(),JZ.clear(),DZ.clear(),xZ.clear(),r4()}}var u="[botmobile]",N7=120,B3,E7=350,P7=524288,R7=50,M7=15000,t4=72,w7=86400000,a4="[botmobile:hook]",z3="generating response",e4=48,S7=500,j7=3000,C7,k7,A7,LZ=null,H0=null,Z5=null,L3=0,w0,N3,lZ,wZ,E3,cZ,D3,U3,F3,rZ,JZ,DZ,xZ,dZ,S3,k3,zZ,R0=null,M0=null;var V0=KZ(()=>{q0();K0();i3();Q0();P4();u4();n4();W7.setDefaultResultOrder("ipv4first");B3=Number.MAX_SAFE_INTEGER,C7=/^agent:[^:]+:botmobil[e]?:direct:(.+)$/i,k7=/^agent:conversation:([^:]+):main$/i,A7=/^agent:[^:]+:cron:([^:]+)(?::run:[^:]+)?$/i,w0=new Map,N3=new Map,lZ=new Map,wZ=new Map,E3=new Map,cZ=new Map,D3=new Map,U3=new Map,F3=new Map,rZ=new Map,JZ=new Map,DZ=new Map,xZ=new Set;dZ=[],S3=[],k3=[],zZ=new Map});import{emptyPluginConfigSchema as P8}from"openclaw/plugin-sdk";V0();import W8 from"qrcode-terminal";import z8 from"ws";var sZ="https://botmobile.vantis.ai";var NZ="[botmobile]";function N8(Z,$){let Q=JSON.stringify({v:2,c:Z,w:$}),X=Buffer.from(Q).toString("base64url");W8.generate(`botmobile://${X}`,{small:!0},(Y)=>{console.log(`
12
+ `)}let _=H3(U);if(_>0){let P=dZ.get(q.agentId)??{in:0,out:0};P.in+=_,dZ.set(q.agentId,P)}let N=Y.channel.reply.formatAgentEnvelope({channel:"BotMobile",from:`user:${$.from}`,timestamp:$.timestamp,envelope:Y.channel.reply.resolveEnvelopeFormatOptions(V),body:U}),W=Y.channel.reply.finalizeInboundContext({Body:N,RawBody:$.body,CommandBody:$.body,From:`botmobile:user:${J}`,To:"botmobile:bot:default",SessionKey:q.sessionKey,AccountId:q.accountId,ChatType:"direct",ConversationLabel:J,SenderName:"User",SenderId:J,Provider:"botmobile",Surface:"botmobile",MessageSid:$.id,OriginatingChannel:"botmobile",OriginatingTo:"botmobile:bot:default"}),h=Y.channel.session.resolveStorePath(V.session?.store,{agentId:q.agentId});await Y.channel.session.recordInboundSession({storePath:h,sessionKey:W.SessionKey??q.sessionKey,ctx:W,updateLastRoute:{sessionKey:q.mainSessionKey,channel:"botmobile",to:`botmobile:user:${J}`,accountId:q.accountId},onRecordError:(P)=>{H.error(`Failed updating session meta: ${String(P)}`)}});let{onModelSelected:A,...p}=P5({cfg:V,agentId:q.agentId,channel:"botmobile",accountId:X}),b=new AbortController;S0.set(J,b);let w=(P,f)=>{k({type:"error",code:P,message:f,conversationId:J})};k({type:"composing",conversationId:J,from:"bot"});let c=Date.now();kZ(q.agentId,"working",{activeConversationId:J,activeTool:_1},V);let j=crypto.randomUUID(),E=!1,v="",z=0,m=0,x="unknown",l=0,n="",XZ="",d=null,hZ=!1,x0=null,T0=()=>{if(!XZ)return;if(l>=B1){XZ="";return}if(!E)k({type:"stream_start",conversationId:J,messageId:j}),E=!0;k({type:"stream_token",conversationId:J,messageId:j,token:XZ}),XZ="",l+=1},C3=()=>{if(d||l>=B1)return;d=setTimeout(()=>{d=null,T0()},M5)};try{await Y.channel.reply.dispatchReplyWithBufferedBlockDispatcher({ctx:W,cfg:V,dispatcherOptions:{...p,deliver:async(P)=>{let f=[];if(typeof P.text==="string"&&P.text.trim().length>0)f.push(P.text);if(typeof P.mediaUrl==="string"&&P.mediaUrl.trim().length>0)f.push(P.mediaUrl);if(Array.isArray(P.mediaUrls)){for(let h0 of P.mediaUrls)if(typeof h0==="string"&&h0.trim().length>0)f.push(h0)}let FZ=f.join(`
13
+ `).trim();if(!FZ)return;n=FZ,k({type:"message",id:j,conversationId:J,from:"bot",body:FZ,timestamp:Date.now()}),hZ=!0}},replyOptions:{onModelSelected:A,onAgentRunStart:()=>{if(E)return;k({type:"stream_start",conversationId:J,messageId:j}),E=!0},onPartialReply:(P)=>{let f=P.text;if(!f)return;m+=1;let FZ="";if(f.startsWith(v)){if(FZ=f.slice(v.length),x==="unknown")x="cumulative"}else if(!v.startsWith(f)){if(FZ=f,x==="unknown")x="incremental"}if(v=f,!FZ)return;if(z+=FZ.length,l>=B1)return;if(XZ+=FZ,XZ.length>=R5){if(d)clearTimeout(d),d=null;T0()}else C3()}}})}catch(P){x0=P instanceof Error?P.message:String(P)}finally{if(d)clearTimeout(d),d=null;if(T0(),E)k({type:"stream_end",conversationId:J,messageId:j,body:n}),hZ=!0;let P=n?H3(n):Math.max(0,Math.ceil(z/4));if(P>0){let f=dZ.get(q.agentId)??{in:0,out:0};f.out+=P,dZ.set(q.agentId,f)}kZ(q.agentId,"idle",{activeElapsedMs:Date.now()-c},V),console.log(`${u} [stream] conv=${J} msg=${j.slice(0,8)} callbacks=${m} mode=${x} streamedChars=${z} tokenEvents=${l} finalLen=${n.length}`),S0.delete(J)}if(x0){if(b.signal.aborted){w("GENERATION_STOPPED","Generation stopped.");return}w("REPLY_FAILED",x0.trim()||"Failed to generate a reply.");return}if(!hZ)w("NO_REPLY","No response generated. Please try again.")}async function G6(Z){let{envelope:$,accountId:X,config:Q,core:Y,logger:H}=Z,V=Q;switch($.type){case"message":{if($.from!=="user")return;await F6({envelope:$,accountId:X,config:Q,core:Y,logger:H});return}case"stop_generation":{let J=R($.conversationId),q=S0.get(J);if(q)q.abort(),S0.delete(J);return}case"state_sync_request":{J3(V,$);return}case"client_state":return;case"cron_list_request":{RZ(V,{includeDisabled:$.includeDisabled===!0,force:!0});return}case"cron_run":{let J=await i1(V,$.jobId);if(!J.ok)k({type:"error",code:"cron_run_failed",message:J.error??"unknown"});else RZ(V,{includeDisabled:!0});return}case"cron_toggle":{let J=await r1(V,$.jobId,$.enabled);if(!J.ok)k({type:"error",code:"cron_toggle_failed",message:J.error??"unknown"});else RZ(V,{includeDisabled:!0});return}case"cron_create_from_prompt":{let J=G3(V,$.agentId),q=g($.description);if(!J||!q){k({type:"error",code:"cron_create_invalid",message:"Agent and description are required to create a task."});return}let O=await s1(V,{name:H6($.name,q),description:q,agentId:J,enabled:!0,schedule:{kind:"every",everyMs:V6($.everyMs)},sessionTarget:"isolated",wakeMode:"now",payload:{kind:"agentTurn",message:q}});if(!O.ok)k({type:"error",code:"cron_create_failed",message:O.error??"unknown"});else RZ(V,{includeDisabled:!0});return}case"cron_runs_request":{let J=d1(V,$.jobId,$.limit??20);k({type:"cron_runs",jobId:$.jobId,runs:J.filter((q)=>q.status).map((q)=>({ts:q.ts,status:q.status,durationMs:q.durationMs,summary:q.summary,error:q.error}))});return}case"subscribe":{let J=$.topics.includes("agents"),q=$.topics.includes("cron");if(J)k({type:"agent_list",agents:k0(V)});if(q)RZ(V,{includeDisabled:!0,force:!0});J3(V);return}default:return}}function W6(){return iZ.length}function G1(Z,$){let X=null;return()=>{if(X)clearTimeout(X);X=setTimeout(()=>{X=null,Z()},$),w1.push(X)}}function W1(Z){let $=Z1(Z).map((V)=>({...V})),X=new Set($.map((V)=>V.sessionFile)),Q=new Set($.slice(0,w5).map((V)=>V.sessionFile)),Y=_Z.size===0;for(let V of $)if(!_Z.has(V.sessionFile))try{let J=w0(V.sessionFile),O=!Y||Q.has(V.sessionFile)?Math.max(0,J.size-S5):J.size;_Z.set(V.sessionFile,{offset:O})}catch{_Z.set(V.sessionFile,{offset:0})}for(let V of _Z.keys())if(!X.has(V))_Z.delete(V);let H=Date.now();for(let V of $){if(V.kind!=="cron")continue;let J=V.cronJobId;if(!J)continue;let q=q1(J),O=SZ(Z,V.agentId),B=V.cronLabel??q?.name,K=V.cronAgentId??q?.agentId??V.agentId,L=V.cronAgentName??q?.agentName??O.name,D=V.cronAgentEmoji??q?.agentEmoji??O.emoji;V.cronLabel=B??V.cronLabel,V.cronAgentId=K,V.cronAgentName=L,V.cronAgentEmoji=D,E0({id:J,name:B,agentId:K,agentName:L,agentEmoji:D,updatedAt:Math.max(V.updatedAt||0,H)}),s0({conversationId:V.conversationId,cronJobId:J,cronName:B,cronAgentId:K,cronAgentName:L,cronAgentEmoji:D},V.updatedAt||H)}k1=$,console.log(`${u} [watcher] refreshed session mappings: ${$.length} transcripts tracked`)}function z1(Z){let $=0,X=q3(Z);for(let Q of k1){let Y=_Z.get(Q.sessionFile)??{offset:0},H=R2(Q.sessionFile,Q,Z,Y,X);if(_Z.set(Q.sessionFile,H.cursor),Q.kind==="cron"&&Q.cronJobId)s0({conversationId:Q.conversationId,cronJobId:Q.cronJobId,cronName:Q.cronLabel,cronAgentId:Q.cronAgentId??Q.agentId,cronAgentName:Q.cronAgentName,cronAgentEmoji:Q.cronAgentEmoji},Q.updatedAt||Date.now());for(let V of H.messages)if(q2({conversationId:V.conversationId,agent:V.agent,role:V.role,content:V.content,timestamp:V.timestamp,stableId:V.stableId}))$++}if($>0)console.log(`${u} [tailer] ingested ${$} new transcript messages`)}function z6(Z){let $=UZ.join(rZ.homedir(),".openclaw"),X=N6(Z);try{let H=K1(X,G1(()=>{console.log(`${u} [watcher] cron jobs.json changed, reloading`),RZ(Z,{includeDisabled:!0})},500));iZ.push(H),console.log(`${u} [watcher] watching cron: ${X}`)}catch(H){console.warn(`${u} [watcher] failed to watch cron store: ${String(H)}`)}let Q=UZ.join($,"agents");try{let H=K1(Q,{recursive:!0},G1(()=>{W1(Z),z1(Z)},1500));iZ.push(H),console.log(`${u} [watcher] watching sessions: ${Q}`)}catch(H){console.warn(`${u} [watcher] failed to watch agents dir: ${String(H)}`)}W1(Z),z1(Z),R0=setInterval(()=>z1(Z),5000),M0=setInterval(()=>W1(Z),60000);let Y=UZ.join($,"openclaw.json");try{let H=K1(Y,G1(()=>{console.log(`${u} [watcher] config changed, re-resolving agents`),k({type:"agent_list",agents:k0(Z)})},1000));iZ.push(H),console.log(`${u} [watcher] watching config: ${Y}`)}catch(H){console.warn(`${u} [watcher] failed to watch config: ${String(H)}`)}}function _6(){if(R0)clearInterval(R0),R0=null;if(M0)clearInterval(M0),M0=null;for(let Z of w1)clearTimeout(Z);w1=[];for(let Z of iZ)try{Z.close()}catch{}iZ.length=0,_Z.clear(),k1=[]}function N6(Z){let $=Z.cron?.store;if(typeof $==="string"&&$.trim()){let X=$.trim();if(X.startsWith("~"))return UZ.resolve(X.replace("~",rZ.homedir()));return UZ.resolve(X)}return UZ.join(rZ.homedir(),".openclaw","cron","jobs.json")}async function z3(Z){let{account:$,accountId:X,config:Q,abortSignal:Y,runtime:H}=Z,V=Q,J=J0(),q={info:(K)=>H.log(K),error:(K)=>H.error(K)};if(LZ)LZ.stop(),LZ=null;let O=null,B=null;o2(),Y2();try{let K=M2(V,q3(V));if(K.length>0){for(let L of K){if(L.kind!=="cron"||!L.cronJobId)continue;E0({id:L.cronJobId,name:L.cronName,agentId:L.cronAgentId,agentName:L.cronAgentName,agentEmoji:L.cronAgentEmoji,updatedAt:L.updatedAt})}H2(K)}}catch(K){console.error(`${u} failed to load historical conversations: ${String(K)}`)}try{N1.clear(),sZ.clear(),JZ.clear(),DZ.clear(),AZ.clear(),MZ.clear(),E1.clear(),lZ.clear(),D6(V),z6(V),O=new H1({account:$,onLegacyEnvelope:(K)=>{G6({envelope:K,accountId:X,config:Q,core:J,logger:q}).catch((L)=>{q.error(`${u} inbound envelope handling failed: ${String(L)}`)})},onSignalingStatus:(K)=>{q.info(`${u} signaling ${K?"connected":"disconnected"}`)},onDataChannelStatus:(K)=>{q.info(`${u} datachannel ${K?"connected":"disconnected"}`)}}),LZ=O,B=O.run(Y).catch((K)=>{q.error(`${u} transport run failed: ${String(K)}`)}),k({type:"agent_list",agents:k0(V)}),RZ(V,{includeDisabled:!0,force:!0}),await new Promise((K)=>{if(Y.aborted){K();return}Y.addEventListener("abort",()=>K(),{once:!0})})}finally{if(O){if(O.stop(),LZ===O)LZ=null}if(B)await B;_6(),U6(),sZ.clear(),JZ.clear(),DZ.clear(),AZ.clear(),n2()}}var u="[botmobile]",R5=120,B1,M5=350,S5=524288,w5=50,j5=15000,Z3=72,C5=86400000,$3="[botmobile:hook]",_1="generating response",X3=48,k5=500,A5=3000,x5,T5,h5,LZ=null,H0=null,Q3=null,L1=0,S0,N1,dZ,MZ,E1,lZ,D1,U1,F1,sZ,JZ,DZ,AZ,iZ,w1,k1,_Z,R0=null,M0=null;var V0=OZ(()=>{q0();O0();o1();X0();S2();g2();e2();E5.setDefaultResultOrder("ipv4first");B1=Number.MAX_SAFE_INTEGER,x5=/^agent:[^:]+:botmobil[e]?:direct:(.+)$/i,T5=/^agent:conversation:([^:]+):main$/i,h5=/^agent:[^:]+:cron:([^:]+)(?::run:[^:]+)?$/i,S0=new Map,N1=new Map,dZ=new Map,MZ=new Map,E1=new Map,lZ=new Map,D1=new Map,U1=new Map,F1=new Map,sZ=new Map,JZ=new Map,DZ=new Map,AZ=new Set;iZ=[],w1=[],k1=[],_Z=new Map});import{Type as S6}from"@sinclair/typebox";import{emptyPluginConfigSchema as w6}from"openclaw/plugin-sdk";V0();import E6 from"qrcode-terminal";import P6 from"ws";var xZ="https://botmobile.vantis.ai";var TZ="[botmobile]";function R6(Z,$){let X=JSON.stringify({v:2,c:Z,w:$}),Q=Buffer.from(X).toString("base64url");E6.generate(`botmobile://${Q}`,{small:!0},(Y)=>{console.log(`
14
14
  Scan this QR code with the BotMobile app:
15
15
  `),console.log(Y),console.log(`
16
16
  Or enter code manually: ${Z}
17
- `)})}async function G5(Z){let $=sZ;console.log(`${NZ} initiating pairing with worker=${$}`),console.log(`${NZ} instance=${Z}`);let Q=await fetch(`${$}/api/pair/init`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ocInstanceId:Z})});if(!Q.ok){let V=await Q.text();throw console.error(`${NZ} pairing init failed: ${Q.status} ${V}`),Error(`Failed to initiate pairing: ${V}`)}let X=await Q.json(),Y=(X.pairingCode??X.pairingId??"").toUpperCase();if(!/^[A-Z0-9]{4}-[A-Z0-9]{4}$/.test(Y))throw Error("Pairing init response missing valid pairing code");console.log(`${NZ} code=${Y}`),console.log(`${NZ} pairing code registered, showing QR`),N8(Y,$);let H=`${$.replace(/^http/,"ws")}/ws/pair?code=${encodeURIComponent(Y)}`;return console.log(`${NZ} connecting to pairing WS...`),new Promise((V,J)=>{let K=new z8(H),B=setTimeout(()=>{K.close(),J(Error("Pairing timed out"))},600000);K.on("open",()=>{console.log(`${NZ} pairing WS connected, waiting for phone...`)}),K.on("message",(O)=>{let L=JSON.parse(O.toString());if(L.type==="paired"&&L.userId&&L.sharedSecret)clearTimeout(B),K.close(),console.log(`${NZ} ✓ pairing complete! userId=${L.userId}`),V({userId:L.userId,sharedSecret:L.sharedSecret,pushSecret:L.pushSecret})}),K.on("close",()=>{clearTimeout(B)}),K.on("error",(O)=>{clearTimeout(B),console.error(`${NZ} pairing WS error: ${O.message}`),J(Error(`Pairing WS error: ${O.message}`))})})}var A0="[botmobile]";function W5(Z){return Z.channels?.botmobile}function z5(Z,$){let Q=Z.channels??{},X={...Q.botmobile??{}};return delete X.workerUrl,{...Z,channels:{...Q,botmobile:{...X,...$}}}}var N5={channel:"botmobile",async getStatus(Z){let $=W5(Z.cfg),Q=!!$?.sharedSecret,X=$?.enabled!==!1,Y=[];if(Q){if(Y.push(`BotMobile: paired (user: ${$?.userId?.slice(0,8)??"?"}...)`),Y.push(` Worker: ${sZ}`),typeof $?.pushSecret==="string"&&$.pushSecret.length>0)Y.push(" Push auth: configured");else Y.push(" Push auth: missing");if(!X)Y.push(" (disabled)")}else Y.push("BotMobile: not configured");return{channel:"botmobile",configured:Q,statusLines:Y,selectionHint:Q?void 0:"Pair your phone via QR code"}},async configure(Z){if(W5(Z.cfg)?.sharedSecret){if(!await Z.prompter.confirm({message:"BotMobile is already paired. Re-pair with a new device?"}))return{cfg:Z.cfg,accountId:"default"}}console.log(`${A0} starting pairing flow...`),await Z.prompter.note(`Scan the QR code below with the BotMobile iOS app.
18
- Or enter the code manually in the app.`,"BotMobile Pairing");let Q=crypto.randomUUID(),X=await G5(Q);console.log(`${A0} pairing complete, saving config`);let Y=z5(Z.cfg,{enabled:!0,sharedSecret:X.sharedSecret,pushSecret:X.pushSecret??"",userId:X.userId}),V=Y.channels;return console.log(`${A0} updatedCfg.channels keys: ${V?Object.keys(V).join(", "):"MISSING"}`),console.log(`${A0} updatedCfg.channels.botmobile: ${V?.botmobile?"present":"MISSING"}`),await Z.prompter.note(`Paired successfully! User ID: ${X.userId.slice(0,8)}...
19
- The gateway will now connect to your phone.`,"BotMobile Connected"),{cfg:Y,accountId:"default"}},disable(Z){return z5(Z,{enabled:!1})}};q0();Q0();var qZ="[botmobile]",E5=new Map;function P5(Z){let $=Z.trim();if(!$)return Z;let Q=":user:",X=$.indexOf(Q);if(X>=0){let Y=$.slice(X+Q.length).trim();if(Y.length>0)return Y}return $}function E8(Z,$){if(!$)return Z;if(Z.startsWith($))return Z;return`${$} ${Z}`.trim()}function R5(Z){let{cfg:$,accountId:Q,conversationId:X}=Z,Y=null;try{Y=J0().channel.routing.resolveAgentRoute({cfg:$,channel:"botmobile",accountId:Q??"default",peer:{kind:"direct",id:X}})}catch(B){console.warn(`${qZ} outbound metadata route failed conv=${X}: ${String(B)}`);return}let H=Y.agentId;if(typeof H!=="string"||!H.trim())return;let V=bZ($,H);F0(X,{id:H,name:V.name,emoji:V.emoji});let J=E8(V.name,V.emoji);if(E5.get(X)===J)return;let K=Date.now();k({type:"conversation_list",conversations:[{id:X,name:J,createdAt:K,lastActivity:K}]}),E5.set(X,J),console.log(`${qZ} outbound conversation meta conv=${X} agent=${H} name="${J}" source=${V.source} emojiSource=${V.emojiSource??"none"}`)}var M5={id:"botmobile",meta:{id:"botmobile",label:"BotMobile",selectionLabel:"BotMobile (Mobile)",docsPath:"/channels/botmobile",blurb:"Mobile bridge for OpenClaw"},pairing:{idLabel:"botmobileUserId"},onboarding:N5,capabilities:{chatTypes:["direct"]},reload:{configPrefixes:["channels.botmobile"]},config:{listAccountIds:(Z)=>{let $=Z.channels?.botmobile,Q=!!$?.sharedSecret;return console.log(`${qZ} listAccountIds: botmobile=${!!$} sharedSecret=${Q}`),Q?["default"]:[]},resolveAccount:(Z,$)=>{let Q=Z.channels?.botmobile;return{sharedSecret:Q?.sharedSecret??"",pushSecret:Q?.pushSecret??"",userId:Q?.userId??"",workerUrl:sZ,enabled:Q?.enabled!==!1}},defaultAccountId:()=>"default",isConfigured:(Z,$)=>{return!!$.channels?.botmobile?.sharedSecret},isEnabled:(Z)=>Z?.enabled!==!1,describeAccount:(Z)=>({accountId:"default",enabled:Z?.enabled!==!1,configured:!!Z?.sharedSecret})},outbound:{deliveryMode:"hybrid",sendText:async({cfg:Z,accountId:$,to:Q,text:X})=>{let Y=P5(Q);R5({cfg:Z,accountId:$,conversationId:Y});let H={type:"message",id:crypto.randomUUID(),conversationId:Y,from:"bot",body:X,timestamp:Date.now()};if(Y!==Q)console.log(`${qZ} outbound sendText to=${Q} conv=${Y} (${X.length} chars)`);else console.log(`${qZ} outbound sendText to=${Q} (${X.length} chars)`);return k(H),{channel:"botmobile",messageId:H.id}},sendMedia:async({cfg:Z,accountId:$,to:Q,text:X,mediaUrl:Y})=>{let H=P5(Q);R5({cfg:Z,accountId:$,conversationId:H});let V=X?`${X}
20
- ${Y}`:Y,J={type:"message",id:crypto.randomUUID(),conversationId:H,from:"bot",body:V,timestamp:Date.now()};if(H!==Q)console.log(`${qZ} outbound sendMedia to=${Q} conv=${H} mediaUrl=${Y}`);else console.log(`${qZ} outbound sendMedia to=${Q} mediaUrl=${Y}`);return k(J),{channel:"botmobile",messageId:J.id}}},gateway:{startAccount:async(Z)=>{let{account:$,accountId:Q}=Z;console.log(`${qZ} gateway startAccount id=${Q} user=${$.userId}`),console.log(`${qZ} workerUrl=${$.workerUrl}`),console.log(`${qZ} configured=${!!$.sharedSecret} enabled=${$.enabled}`),Z.setStatus?.({accountId:Q,running:!0,lastStartAt:Date.now(),lastError:null});let{monitorBotMobileProvider:X}=await Promise.resolve().then(() => (V0(),_5));await X({account:$,accountId:Q,config:Z.cfg,runtime:Z.runtime,abortSignal:Z.abortSignal})},stopAccount:async(Z)=>{console.log(`${qZ} gateway stopAccount id=${Z.accountId}`),Z.setStatus?.({accountId:Z.accountId,running:!1,lastStopAt:Date.now()})}}};V0();V0();var R8={id:"botmobile-openclaw",name:"BotMobile",description:"Mobile bridge for OpenClaw",configSchema:P8(),register(Z){A3(Z.runtime),Z.registerChannel({plugin:M5}),Z.on("before_tool_call",($,Q)=>{C0({phase:"start",agentId:Q.agentId,sessionKey:Q.sessionKey,toolName:$.toolName,toolParams:$.params,config:Z.config})}),Z.on("after_tool_call",($,Q)=>{C0({phase:"end",agentId:Q.agentId,sessionKey:Q.sessionKey,toolName:$.toolName,toolParams:$.params,error:$.error,config:Z.config})}),Z.on("agent_end",($,Q)=>{C3({agentId:Q.agentId,sessionKey:Q.sessionKey,success:$.success,error:$.error,config:Z.config})})}},p9=R8;export{F5 as monitorBotMobileProvider,p9 as default};
17
+ `)})}async function A1(Z){let $=xZ;console.log(`${TZ} requesting pairing code from worker=${$}`);let X=await fetch(`${$}/api/pair/init`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ocInstanceId:Z})});if(!X.ok){let J=await X.text();throw console.error(`${TZ} pairing init failed: ${X.status} ${J}`),Error(`Failed to initiate pairing: ${J}`)}let Q=await X.json(),Y=(Q.pairingCode??Q.pairingId??"").toUpperCase();if(!/^[A-Z0-9]{4}-[A-Z0-9]{4}$/.test(Y))throw Error("Pairing init response missing valid pairing code");let H=JSON.stringify({v:2,c:Y,w:$}),V=`botmobile://${Buffer.from(H).toString("base64url")}`;return console.log(`${TZ} pairing code=${Y}`),{pairingCode:Y,deepLink:V,workerUrl:$}}function x1(Z){let X=`${xZ.replace(/^http/,"ws")}/ws/pair?code=${encodeURIComponent(Z)}`;return console.log(`${TZ} waiting for pairing completion on WS...`),new Promise((Q,Y)=>{let V=new P6(X),J=setTimeout(()=>{V.close(),Y(Error("Pairing timed out"))},600000);V.on("open",()=>{console.log(`${TZ} pairing WS connected, waiting for phone...`)}),V.on("message",(q)=>{let O=JSON.parse(q.toString());if(O.type==="paired"&&O.userId&&O.sharedSecret)clearTimeout(J),V.close(),console.log(`${TZ} ✓ pairing complete! userId=${O.userId}`),Q({userId:O.userId,sharedSecret:O.sharedSecret,pushSecret:O.pushSecret})}),V.on("close",()=>{clearTimeout(J)}),V.on("error",(q)=>{clearTimeout(J),console.error(`${TZ} pairing WS error: ${q.message}`),Y(Error(`Pairing WS error: ${q.message}`))})})}async function N3(Z){let{pairingCode:$,workerUrl:X}=await A1(Z);return R6($,X),x1($)}var A0="[botmobile]";function E3(Z){return Z.channels?.botmobile}function P3(Z,$){let X=Z.channels??{},Q={...X.botmobile??{}};return delete Q.workerUrl,{...Z,channels:{...X,botmobile:{...Q,...$}}}}var R3={channel:"botmobile",async getStatus(Z){let $=E3(Z.cfg),X=!!$?.sharedSecret,Q=$?.enabled!==!1,Y=[];if(X){if(Y.push(`BotMobile: paired (user: ${$?.userId?.slice(0,8)??"?"}...)`),Y.push(` Worker: ${xZ}`),typeof $?.pushSecret==="string"&&$.pushSecret.length>0)Y.push(" Push auth: configured");else Y.push(" Push auth: missing");if(!Q)Y.push(" (disabled)")}else Y.push("BotMobile: not configured");return{channel:"botmobile",configured:X,statusLines:Y,selectionHint:X?void 0:"Pair your phone via QR code"}},async configure(Z){if(E3(Z.cfg)?.sharedSecret){if(!await Z.prompter.confirm({message:"BotMobile is already paired. Re-pair with a new device?"}))return{cfg:Z.cfg,accountId:"default"}}console.log(`${A0} starting pairing flow...`),await Z.prompter.note(`Scan the QR code below with the BotMobile iOS app.
18
+ Or enter the code manually in the app.`,"BotMobile Pairing");let X=crypto.randomUUID(),Q=await N3(X);console.log(`${A0} pairing complete, saving config`);let Y=P3(Z.cfg,{enabled:!0,sharedSecret:Q.sharedSecret,pushSecret:Q.pushSecret??"",userId:Q.userId}),V=Y.channels;return console.log(`${A0} updatedCfg.channels keys: ${V?Object.keys(V).join(", "):"MISSING"}`),console.log(`${A0} updatedCfg.channels.botmobile: ${V?.botmobile?"present":"MISSING"}`),await Z.prompter.note(`Paired successfully! User ID: ${Q.userId.slice(0,8)}...
19
+ The gateway will now connect to your phone.`,"BotMobile Connected"),{cfg:Y,accountId:"default"}},disable(Z){return P3(Z,{enabled:!1})}};q0();X0();var qZ="[botmobile]",M3=new Map;function S3(Z){let $=Z.trim();if(!$)return Z;let X=":user:",Q=$.indexOf(X);if(Q>=0){let Y=$.slice(Q+X.length).trim();if(Y.length>0)return Y}return $}function M6(Z,$){if(!$)return Z;if(Z.startsWith($))return Z;return`${$} ${Z}`.trim()}function w3(Z){let{cfg:$,accountId:X,conversationId:Q}=Z,Y=null;try{Y=J0().channel.routing.resolveAgentRoute({cfg:$,channel:"botmobile",accountId:X??"default",peer:{kind:"direct",id:Q}})}catch(B){console.warn(`${qZ} outbound metadata route failed conv=${Q}: ${String(B)}`);return}let H=Y.agentId;if(typeof H!=="string"||!H.trim())return;let V=fZ($,H);F0(Q,{id:H,name:V.name,emoji:V.emoji});let J=M6(V.name,V.emoji);if(M3.get(Q)===J)return;let O=Date.now();k({type:"conversation_list",conversations:[{id:Q,name:J,createdAt:O,lastActivity:O}]}),M3.set(Q,J),console.log(`${qZ} outbound conversation meta conv=${Q} agent=${H} name="${J}" source=${V.source} emojiSource=${V.emojiSource??"none"}`)}var j3={id:"botmobile",meta:{id:"botmobile",label:"BotMobile",selectionLabel:"BotMobile (Mobile)",docsPath:"/channels/botmobile",blurb:"Mobile bridge for OpenClaw"},pairing:{idLabel:"botmobileUserId"},onboarding:R3,capabilities:{chatTypes:["direct"]},reload:{configPrefixes:["channels.botmobile"]},config:{listAccountIds:(Z)=>{let $=Z.channels?.botmobile,X=!!$?.sharedSecret;return console.log(`${qZ} listAccountIds: botmobile=${!!$} sharedSecret=${X}`),X?["default"]:[]},resolveAccount:(Z,$)=>{let X=Z.channels?.botmobile;return{sharedSecret:X?.sharedSecret??"",pushSecret:X?.pushSecret??"",userId:X?.userId??"",workerUrl:xZ,enabled:X?.enabled!==!1}},defaultAccountId:()=>"default",isConfigured:(Z,$)=>{return!!$.channels?.botmobile?.sharedSecret},isEnabled:(Z)=>Z?.enabled!==!1,describeAccount:(Z)=>({accountId:"default",enabled:Z?.enabled!==!1,configured:!!Z?.sharedSecret})},outbound:{deliveryMode:"hybrid",sendText:async({cfg:Z,accountId:$,to:X,text:Q})=>{let Y=S3(X);w3({cfg:Z,accountId:$,conversationId:Y});let H={type:"message",id:crypto.randomUUID(),conversationId:Y,from:"bot",body:Q,timestamp:Date.now()};if(Y!==X)console.log(`${qZ} outbound sendText to=${X} conv=${Y} (${Q.length} chars)`);else console.log(`${qZ} outbound sendText to=${X} (${Q.length} chars)`);return k(H),{channel:"botmobile",messageId:H.id}},sendMedia:async({cfg:Z,accountId:$,to:X,text:Q,mediaUrl:Y})=>{let H=S3(X);w3({cfg:Z,accountId:$,conversationId:H});let V=Q?`${Q}
20
+ ${Y}`:Y,J={type:"message",id:crypto.randomUUID(),conversationId:H,from:"bot",body:V,timestamp:Date.now()};if(H!==X)console.log(`${qZ} outbound sendMedia to=${X} conv=${H} mediaUrl=${Y}`);else console.log(`${qZ} outbound sendMedia to=${X} mediaUrl=${Y}`);return k(J),{channel:"botmobile",messageId:J.id}}},gateway:{startAccount:async(Z)=>{let{account:$,accountId:X}=Z;console.log(`${qZ} gateway startAccount id=${X} user=${$.userId}`),console.log(`${qZ} workerUrl=${$.workerUrl}`),console.log(`${qZ} configured=${!!$.sharedSecret} enabled=${$.enabled}`),Z.setStatus?.({accountId:X,running:!0,lastStartAt:Date.now(),lastError:null});let{monitorBotMobileProvider:Q}=await Promise.resolve().then(() => (V0(),_3));await Q({account:$,accountId:X,config:Z.cfg,runtime:Z.runtime,abortSignal:Z.abortSignal})},stopAccount:async(Z)=>{console.log(`${qZ} gateway stopAccount id=${Z.accountId}`),Z.setStatus?.({accountId:Z.accountId,running:!1,lastStopAt:Date.now()})}}};V0();V0();var T1="[botmobile]";function j6(Z){return{name:"botmobile_pair",label:"BotMobile Pair",description:"Start BotMobile phone pairing. Returns a pairing code and deep link to send to the user. The user opens the BotMobile iOS app and enters the code (or taps the deep link). "+"Pairing completes automatically in the background — config is saved and the channel reloads.",parameters:S6.Object({}),execute:async()=>{let $=crypto.randomUUID(),{pairingCode:X,deepLink:Q}=await A1($);return x1(X).then(async(Y)=>{try{let H=Z.runtime.config.loadConfig(),V=H.channels??{},J={...H,channels:{...V,botmobile:{...V.botmobile??{},enabled:!0,sharedSecret:Y.sharedSecret,pushSecret:Y.pushSecret??"",userId:Y.userId}}};await Z.runtime.config.writeConfigFile(J),console.log(`${T1} pairing saved to config (userId=${Y.userId}). Channel will reload automatically.`)}catch(H){console.error(`${T1} failed to save pairing config: ${String(H)}`)}}).catch((Y)=>{console.warn(`${T1} pairing wait failed: ${String(Y)}`)}),{content:[{type:"text",text:JSON.stringify({pairingCode:X,deepLink:Q,message:"Send the pairing code and deep link to the user. They need the BotMobile iOS app. After the user pairs, the config is saved automatically and the channel connects."},null,2)}]}}}}var C6={id:"botmobile-openclaw",name:"BotMobile",description:"Mobile bridge for OpenClaw",configSchema:w6(),register(Z){h1(Z.runtime),Z.registerChannel({plugin:j3}),Z.registerTool(j6(Z)),Z.on("before_tool_call",($,X)=>{C0({phase:"start",agentId:X.agentId,sessionKey:X.sessionKey,toolName:$.toolName,toolParams:$.params,config:Z.config})}),Z.on("after_tool_call",($,X)=>{C0({phase:"end",agentId:X.agentId,sessionKey:X.sessionKey,toolName:$.toolName,toolParams:$.params,error:$.error,config:Z.config})}),Z.on("agent_end",($,X)=>{C1({agentId:X.agentId,sessionKey:X.sessionKey,success:$.success,error:$.error,config:Z.config})})}},o7=C6;export{z3 as monitorBotMobileProvider,o7 as default};
package/package.json CHANGED
@@ -1,16 +1,14 @@
1
1
  {
2
2
  "name": "@botmobile/botmobile-openclaw",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "OpenClaw BotMobile mobile bridge plugin (private test build)",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist/",
8
8
  "openclaw.plugin.json",
9
- "scripts/postinstall.mjs"
9
+ "INSTALL.md"
10
10
  ],
11
- "scripts": {
12
- "postinstall": "node scripts/postinstall.mjs"
13
- },
11
+ "scripts": {},
14
12
  "dependencies": {
15
13
  "msgpackr": "^1.11.5",
16
14
  "node-datachannel": "^0.25.0",
@@ -1,48 +0,0 @@
1
- import { execSync } from "node:child_process";
2
- import { dirname, join } from "node:path";
3
- import { existsSync } from "node:fs";
4
- import { fileURLToPath } from "node:url";
5
-
6
- const __dirname = dirname(fileURLToPath(import.meta.url));
7
- const ndcDir = join(__dirname, "..", "node_modules", "node-datachannel");
8
-
9
- if (!existsSync(ndcDir)) {
10
- console.error("[botmobile] node-datachannel not found at", ndcDir);
11
- process.exit(1);
12
- }
13
-
14
- const binaryPath = join(ndcDir, "build", "Release", "node_datachannel.node");
15
-
16
- if (existsSync(binaryPath)) {
17
- // Binary exists, all good
18
- process.exit(0);
19
- }
20
-
21
- console.log("[botmobile] node-datachannel native binary not found, running prebuild-install…");
22
-
23
- // Try prebuild-install (downloads prebuilt binary from GitHub releases)
24
- try {
25
- execSync("npx prebuild-install -r napi --verbose", {
26
- cwd: ndcDir,
27
- stdio: "inherit",
28
- timeout: 120_000,
29
- });
30
- } catch {
31
- console.error(
32
- "[botmobile] prebuild-install failed. The native binary for node-datachannel could not be downloaded."
33
- );
34
- console.error(
35
- "[botmobile] To build from source, install build tools and run:"
36
- );
37
- console.error(` apt-get install -y build-essential cmake`);
38
- console.error(` cd ${ndcDir} && npx cmake-js compile -r napi`);
39
- process.exit(1);
40
- }
41
-
42
- // Verify the binary was actually created
43
- if (!existsSync(binaryPath)) {
44
- console.error("[botmobile] prebuild-install completed but binary still missing at:", binaryPath);
45
- process.exit(1);
46
- }
47
-
48
- console.log("[botmobile] node-datachannel native binary installed successfully");