@botmobile/botmobile-openclaw 0.0.11 → 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 +109 -0
- package/dist/index.js +15 -15
- package/package.json +3 -5
- package/scripts/postinstall.mjs +0 -44
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
|
-
`),
|
|
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?
|
|
7
|
-
`):
|
|
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
|
|
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(
|
|
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
|
|
18
|
-
Or enter the code manually in the app.`,"BotMobile Pairing");let
|
|
19
|
-
The gateway will now connect to your phone.`,"BotMobile Connected"),{cfg:Y,accountId:"default"}},disable(Z){return
|
|
20
|
-
${Y}`:Y,J={type:"message",id:crypto.randomUUID(),conversationId:H,from:"bot",body:V,timestamp:Date.now()};if(H!==
|
|
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.
|
|
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
|
-
"
|
|
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",
|
package/scripts/postinstall.mjs
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { execSync } from "node:child_process";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
import { existsSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
|
|
6
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
const pluginRoot = join(__dirname, "..");
|
|
8
|
-
|
|
9
|
-
// Write marker so we can verify postinstall ran
|
|
10
|
-
writeFileSync(join(pluginRoot, ".postinstall-ran"), new Date().toISOString());
|
|
11
|
-
|
|
12
|
-
const ndcDir = join(pluginRoot, "node_modules", "node-datachannel");
|
|
13
|
-
|
|
14
|
-
if (!existsSync(ndcDir)) {
|
|
15
|
-
console.error("[botmobile:postinstall] node-datachannel not found at", ndcDir);
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const binaryPath = join(ndcDir, "build", "Release", "node_datachannel.node");
|
|
20
|
-
|
|
21
|
-
if (existsSync(binaryPath)) {
|
|
22
|
-
console.log("[botmobile:postinstall] native binary already exists");
|
|
23
|
-
process.exit(0);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
console.log("[botmobile:postinstall] native binary missing, running prebuild-install…");
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
execSync("npx prebuild-install -r napi --verbose", {
|
|
30
|
-
cwd: ndcDir,
|
|
31
|
-
stdio: "inherit",
|
|
32
|
-
timeout: 120_000,
|
|
33
|
-
});
|
|
34
|
-
} catch {
|
|
35
|
-
console.error("[botmobile:postinstall] prebuild-install failed");
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (!existsSync(binaryPath)) {
|
|
40
|
-
console.error("[botmobile:postinstall] prebuild-install ran but binary still missing at:", binaryPath);
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
console.log("[botmobile:postinstall] native binary installed successfully");
|