shadow-claw 1.24.0 → 1.25.0
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.
- package/README.md +2 -1
- package/bin/cli.mjs +111 -2
- package/bin/commands/webrtc-listen.mjs +21 -1
- package/bin/utils/control-client.mjs +44 -30
- package/bin/utils/control-client.test.mjs +10 -0
- package/bin/utils/webrtc-control-client.mjs +23 -4
- package/dist/public/AGENTS.md +8 -1
- package/dist/public/README.md +2 -1
- package/dist/public/agent.worker.js +49 -49
- package/dist/public/backup-controller-CvzDOq4T.js +1 -0
- package/dist/public/{configurePeerJs-CxpZeDJJ.js → configurePeerJs-UfQ6HUlv.js} +1 -1
- package/dist/public/docs/README.md +1 -1
- package/dist/public/docs/example/article/index.html +1 -1
- package/dist/public/docs/guides/server-development-configuration.md +28 -0
- package/dist/public/docs/publishing/index.html +1 -1
- package/dist/public/docs/skill-creator/index.html +1 -1
- package/dist/public/docs/subsystems/cli.md +25 -19
- package/dist/public/docs/subsystems/control-plane.md +11 -0
- package/dist/public/{downloadGroupFile-By0GR6eV.js → downloadGroupFile-9niHBj9n.js} +1 -1
- package/dist/public/{e2e-bridge-IGWsRl4i.js → e2e-bridge-D28tOggc.js} +1 -1
- package/dist/public/{file-viewer-D0eflgt6.js → file-viewer-BVg3B_JH.js} +1 -1
- package/dist/public/index.html +1 -1
- package/dist/public/index.js +1 -1
- package/dist/public/initControlPlane-D5kHKcB5.js +1 -0
- package/dist/public/llms.txt +1 -1
- package/dist/public/main/index.html +1 -1
- package/dist/public/main/memory/index.html +1 -1
- package/dist/public/{markdown-BnpKxSxl.js → markdown-SiFq0PTy.js} +1 -1
- package/dist/public/{orchestrator-nJj59RqD.js → orchestrator-CnwkoBpe.js} +1 -1
- package/dist/public/{orchestrator-3h9xxHUm.js → orchestrator-tHWrqi_F.js} +5 -5
- package/dist/public/{peerjs-BP4laMXj.js → peerjs-CuSJUH-r.js} +1 -1
- package/dist/public/push-client-D0lkwrK0.js +1 -0
- package/dist/public/service-worker/fetch-proxy.js +1 -1
- package/dist/public/service-worker.js +1 -1
- package/dist/public/{shadow-claw-CbwETBWf.js → shadow-claw-CUbhMmcB.js} +2 -2
- package/dist/public/{shadow-claw-channels-BDWG5Qa3.js → shadow-claw-channels-mY-JMvib.js} +1 -1
- package/dist/public/{shadow-claw-chat-Crv0DTCY.js → shadow-claw-chat-BN85a1xk.js} +1 -1
- package/dist/public/{shadow-claw-control-plane-CX1IGbh9.js → shadow-claw-control-plane-C0lSxLpW.js} +2 -2
- package/dist/public/{shadow-claw-conversations-_9qAaRXk.js → shadow-claw-conversations-0Q-VC_7N.js} +1 -1
- package/dist/public/{shadow-claw-file-viewer-Blf6yGVD.js → shadow-claw-file-viewer-AZfG4D-u.js} +1 -1
- package/dist/public/{shadow-claw-files-CYySBDCl.js → shadow-claw-files-Bx4v0Ggp.js} +1 -1
- package/dist/public/{shadow-claw-git-v8S0JjuR.js → shadow-claw-git-DD7iQRxq.js} +2 -2
- package/dist/public/{shadow-claw-llm-GWgoVfhI.js → shadow-claw-llm-CfeDBZKB.js} +1 -1
- package/dist/public/{shadow-claw-networking-qHbP95z9.js → shadow-claw-networking-e0EarDVs.js} +1 -1
- package/dist/public/{shadow-claw-notifications-YyHOK2Fr.js → shadow-claw-notifications-BkxuDEQI.js} +3 -3
- package/dist/public/{shadow-claw-pages-DFZHhzFZ.js → shadow-claw-pages-BWSE91I1.js} +1 -1
- package/dist/public/{shadow-claw-settings-DhxrKIfA.js → shadow-claw-settings-BZWrAoQA.js} +2 -2
- package/dist/public/{shadow-claw-storage-BFynbP0j.js → shadow-claw-storage-Crs6LY15.js} +1 -1
- package/dist/public/{shadow-claw-task-server-3BIeb5oZ.js → shadow-claw-task-server-CKm_Ennl.js} +1 -1
- package/dist/public/{shadow-claw-tasks-Caxc9atL.js → shadow-claw-tasks-Czx6Ucf5.js} +1 -1
- package/dist/public/{shadow-claw-terminal-Beb5qF-U.js → shadow-claw-terminal-Dmtr9KY1.js} +1 -1
- package/dist/public/{shadow-claw-tools-BfJx3A9W.js → shadow-claw-tools-t3Qq4TDO.js} +1 -1
- package/dist/public/{shadow-claw-webvm-BCS8ykeP.js → shadow-claw-webvm-CIuSywD_.js} +1 -1
- package/dist/public/{syncWebMcpRegistration-B_M2fCjH.js → syncWebMcpRegistration-DzC80wVG.js} +1 -1
- package/dist/server.js +203 -203
- package/package.json +1 -1
- package/src/components/settings/shadow-claw-notifications/shadow-claw-notifications.test.ts +3 -0
- package/src/components/settings/shadow-claw-notifications/shadow-claw-notifications.ts +43 -9
- package/src/core/backup-controller.ts +33 -4
- package/src/core/control-plane-client.test.ts +9 -2
- package/src/core/control-plane-client.ts +18 -2
- package/src/core/orchestrator/utils/operations/task.ts +46 -15
- package/src/core/utils/initControlPlane.ts +2 -0
- package/src/server/app.ts +2 -0
- package/src/server/config.test.ts +49 -0
- package/src/server/config.ts +47 -0
- package/src/server/control-plane.test.ts +36 -0
- package/src/server/control-plane.ts +41 -14
- package/src/server/middleware/pna.test.ts +15 -3
- package/src/server/middleware/pna.ts +6 -2
- package/src/server/peer.ts +6 -2
- package/src/server/routes/backup.test.ts +14 -0
- package/src/server/routes/backup.ts +44 -15
- package/src/server/server.test.ts +118 -0
- package/src/server/server.ts +22 -5
- package/src/server/tls.test.ts +266 -0
- package/src/server/tls.ts +178 -0
- package/src/service-worker/fetch-proxy-rules.test.ts +41 -0
- package/src/service-worker/fetch-proxy-rules.ts +15 -8
- package/src/service-worker/fetch-proxy.ts +18 -2
- package/src/subsystems/notifications/push-client.test.ts +5 -1
- package/src/subsystems/notifications/push-client.ts +50 -12
- package/dist/public/backup-controller-C_s9in2t.js +0 -1
- package/dist/public/initControlPlane-C9jpnWev.js +0 -1
- package/dist/public/push-client-CrjEXK3U.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{D as e,E as t,F as n,I as r,M as i,O as a,P as o,R as s,T as c,_ as l,g as u,j as d,l as f,o as p,r as m,s as h,t as g,v as _,w as v}from"./config-CrHchneq.js";import{n as y,r as b}from"./txPromise-EBECky1b.js";import{t as x}from"./getConfig-D89uJgo5.js";import{p as S}from"./custom-element-security-NCqQ5lmC.js";import{n as C}from"./toast-60iDlgiH.js";import{At as w,C as T,Ct as E,Dt as ee,En as te,Et as ne,Ft as D,G as O,Gt as k,H as A,Ht as j,I as M,It as N,Jt as P,Kt as F,Lt as I,M as re,Mt as ie,N as L,Nt as R,On as ae,Ot as z,P as oe,Pt as se,St as B,Tn as ce,Tt as le,U as V,Ut as ue,V as de,W as fe,Wt as pe,X as me,Xt as he,Y as ge,Yt as _e,_n as ve,an as ye,at as be,bn as xe,bt as Se,dn as H,dt as Ce,fn as we,ft as Te,gn as Ee,gt as De,hn as Oe,in as ke,j as Ae,jt as je,kt as U,l as Me,ln as Ne,mn as W,on as Pe,ot as Fe,pn as G,qt as Ie,rn as K,t as q,u as Le,un as Re,ut as ze,vn as Be,yn as Ve}from"./orchestrator-3h9xxHUm.js";import{l as He,r as Ue}from"./getGroupDir-P1h9wl6S.js";import{t as J}from"./setConfig-DFMYnYLE.js";import{t as Y}from"./ulid-BY7rQVLN.js";import{a as We,o as Ge,r as Ke,s as qe}from"./syncWebMcpRegistration-B_M2fCjH.js";import{n as Je,r as Ye}from"./crypto-C8c5wMzN.js";import{a as Xe,i as Ze,r as X,t as Qe}from"./peerjs-BP4laMXj.js";async function $e(e){if(!(!e||e.name===`shadowclaw`)){try{if(await x(e,m.DB_MIGRATED_FROM_LEGACY)===`true`)return}catch{}try{let t=await new Promise(e=>{let t=indexedDB.open(l);t.onsuccess=()=>{let n=t.result;if(!n.objectStoreNames||n.objectStoreNames.length===0){n.close(),e(null);return}e(n)},t.onerror=()=>e(null)});if(t){let n=Array.from(t.objectStoreNames).filter(t=>e.objectStoreNames.contains(t));for(let r of n)await new Promise(n=>{try{let i=t.transaction(r,`readonly`).objectStore(r).getAll();i.onsuccess=()=>{let t=i.result||[];if(t.length>0)try{let i=e.transaction(r,`readwrite`),a=i.objectStore(r);for(let e of t)a.put(e);i.oncomplete=()=>n(),i.onerror=()=>n(),i.onabort=()=>n()}catch{n()}else n()},i.onerror=()=>n()}catch{n()}});t.close()}}catch(e){console.warn(`Legacy IndexedDB migration warning:`,e)}finally{try{await J(e,m.DB_MIGRATED_FROM_LEGACY,`true`)}catch{}}}}async function et(e,t,n){for await(let[r,i]of e.entries())if(i.kind===`directory`)await et(i,await t.getDirectoryHandle(r,{create:!0}),[...n,r]);else if(i.kind===`file`){let e=await i.getFile(),a=await t.getFileHandle(r,{create:!0});try{await Ne(a,e)}catch(t){if(!(t instanceof Error?t.message:String(t)).includes(`Writable file streams are not supported`))throw t;await Re([...n,r],e)}}}async function tt(e){if(!e)return;try{if(await x(e,m.OPFS_MIGRATED_FROM_LEGACY)===`true`)return}catch{}let t=Ue();if(t!==`shadowclaw`&&!(typeof navigator>`u`||!navigator.storage||typeof navigator.storage.getDirectory!=`function`))try{let n=await navigator.storage.getDirectory(),r;try{r=await n.getDirectoryHandle(_)}catch{try{await J(e,m.OPFS_MIGRATED_FROM_LEGACY,`true`)}catch{}return}let i=await n.getDirectoryHandle(t,{create:!0});await et(r,i,[t])}catch(e){console.warn(`Legacy OPFS migration warning:`,e)}finally{try{await J(e,m.OPFS_MIGRATED_FROM_LEGACY,`true`)}catch{}}}function nt(){return new Promise(async(e,t)=>{let n,r=d(),i=indexedDB.open(r,2);i.onupgradeneeded=()=>{let e=i.result;if(!e.objectStoreNames.contains(`messages`)){let t=e.createObjectStore(`messages`,{keyPath:`id`});t.createIndex(`by-group-time`,[`groupId`,`timestamp`]),t.createIndex(`by-group`,`groupId`)}if(e.objectStoreNames.contains(`sessions`)||e.createObjectStore(`sessions`,{keyPath:`groupId`}),!e.objectStoreNames.contains(`tasks`)){let t=e.createObjectStore(`tasks`,{keyPath:`id`});t.createIndex(`by-group`,`groupId`),t.createIndex(`by-enabled`,`enabled`)}e.objectStoreNames.contains(`config`)||e.createObjectStore(`config`,{keyPath:`key`}),e.objectStoreNames.contains(`pendingShares`)||e.createObjectStore(`pendingShares`,{keyPath:`id`}).createIndex(`by-createdAt`,`createdAt`)},i.onsuccess=async()=>{n=i.result,b(n);try{await $e(n),await tt(n)}catch(e){console.warn(`Error running legacy migration:`,e)}e(n)},i.onerror=()=>{t(Error(`Failed to open IndexedDB: ${i.error?.message}`))}})}var rt=class{activeGroupId;displayCallback;messageCallback;type;typingCallback;constructor(){this.type=`browser`,this.messageCallback=null,this.typingCallback=null,this.displayCallback=null,this.activeGroupId=p}getActiveGroup(){return this.activeGroupId}onDisplay(e){this.displayCallback=e}onMessage(e){this.messageCallback=e}onTyping(e){this.typingCallback=e}setActiveGroup(e){this.activeGroupId=e}setTyping(e,t){this.typingCallback?.(e,t)}start(){}stop(){}submit(e,t,n=[],r,i,a){let o=t||this.activeGroupId,s={id:Y(),groupId:o,sender:`You`,content:e,timestamp:Date.now(),channel:`browser`,attachments:n,a2uiAction:r,freshContext:i,subagent:a};this.messageCallback?.(s)}async send(e,t,n){this.displayCallback?.(e,t,!0)}},it=class{_entries;constructor(){this._entries=[]}find(e){return this.resolve(e)?.channel??null}get(e){return this._entries.find(t=>t.prefix===e)?.channel}getBadge(e){return this.resolve(e)?.badge??``}getChannelType(e){return this.resolve(e)?.channel.type??null}onMessage(e){for(let t of this._entries)t.channel.onMessage(e)}onTyping(e){for(let t of this._entries)t.channel.onTyping&&t.channel.onTyping(e)}prefixes(){return this._entries.map(e=>e.prefix)}register(e,t,n){let r=typeof n==`string`?{badge:n}:n??{};this._entries.push({prefix:e,channel:t,badge:r.badge??e.replace(/:$/,``),autoTrigger:r.autoTrigger??!1}),this._entries.sort((e,t)=>t.prefix.length-e.prefix.length)}resolve(e){for(let t of this._entries)if(e.startsWith(t.prefix))return t;return null}shouldAutoTrigger(e){return this.resolve(e)?.autoTrigger??!1}startAll(){for(let e of this._entries)e.channel.start()}stopAll(){for(let e of this._entries)e.channel.stop()}},at=class{abortController=null;apiKey=``;apiMode=`unknown`;cursor=null;fileReader=null;messageCallback=null;reconnectDelayMs=1e3;registeredChatIds=new Set;running=!1;seenMessageIds=new Map;serverUrl=``;type=`imessage`;configure(e,t,n){this.serverUrl=ot(e),this.apiKey=t.trim(),this.registeredChatIds=new Set(n.map(e=>e.trim()).filter(Boolean)),this.cursor=null,this.apiMode=`unknown`}handleIncomingMessage(e){this.pruneSeenMessageIds();let t=String(e.chatId||e.conversationId||``).trim();if(!t||this.registeredChatIds.size>0&&!this.registeredChatIds.has(t))return;let n=`${e.text||e.body||``}`.trim();if(!n)return;let r=`${e.id||e.guid||`${t}:${e.timestamp||e.createdAt||n}`}`;if(this.seenMessageIds.has(r))return;this.seenMessageIds.set(r,Date.now());let i={id:r,groupId:`im:${t}`,sender:`${e.sender||e.handle||e.from||`iMessage`}`,content:n,timestamp:st(e.timestamp||e.createdAt),channel:`imessage`};this.messageCallback?.(i)}handlePollResponse(e){e.nextCursor!==void 0&&e.nextCursor!==null?this.cursor=String(e.nextCursor):e.cursor!==void 0&&e.cursor!==null&&(this.cursor=String(e.cursor));let t=Array.isArray(e.messages)?e.messages:[];for(let e of t)this.handleIncomingMessage(e)}isConfigured(){return this.serverUrl.length>0}onMessage(e){this.messageCallback=e}pruneSeenMessageIds(){let e=Date.now();for(let[t,n]of this.seenMessageIds.entries())e-n>6e4&&this.seenMessageIds.delete(t)}setTyping(e,t){if(!t)return;let n=e.replace(/^im:/,``);this.requestJson(`/messages/typing`,{method:`POST`,body:JSON.stringify({chatId:n,typing:!0})}).catch(()=>{})}start(){!this.isConfigured()||this.running||(this.running=!0,this.abortController=new AbortController,this.poll())}stop(){this.running=!1,this.abortController?.abort(),this.abortController=null}async ensureApiMode(){if(this.apiMode!==`unknown`)return this.apiMode;try{await this.requestJson(`/v1/info`,{method:`GET`}),this.apiMode=`beeper-desktop`}catch{this.apiMode=`legacy`}return this.apiMode}async poll(){for(;this.running&&this.abortController&&!this.abortController.signal.aborted;)try{let e=new URLSearchParams({timeout:`25`});this.cursor&&e.set(`cursor`,this.cursor);let t=await this.requestJson(`/messages?${e.toString()}`,{method:`GET`},u+5e3,this.abortController.signal);this.reconnectDelayMs=1e3,this.handlePollResponse(t)}catch(e){if(e instanceof Error&&e.name===`AbortError`)break;console.error(`iMessage bridge poll error:`,e),await ct(this.reconnectDelayMs),this.reconnectDelayMs=Math.min(this.reconnectDelayMs*2,3e4)}}async requestJson(e,t,n=u,r){let i=new AbortController,a=setTimeout(()=>i.abort(),n),o=()=>i.abort();r?.addEventListener(`abort`,o,{once:!0});try{let n=new Headers(t.headers);n.set(`Accept`,`application/json`),!n.has(`Content-Type`)&&t.body&&!(t.body instanceof FormData)&&n.set(`Content-Type`,`application/json`),this.apiKey&&(n.set(`Authorization`,`Bearer ${this.apiKey}`),n.set(`X-API-Key`,this.apiKey));let r=await fetch(`${this.serverUrl}${e}`,{...t,headers:n,signal:i.signal});if(!r.ok){let e=await r.text();throw Error(`iMessage bridge request failed: ${r.status} ${e}`)}return r.status===204?{messages:[]}:await r.json()}finally{clearTimeout(a),r?.removeEventListener(`abort`,o)}}async send(e,t,n){let r=e.replace(/^im:/,``),{remainingText:i,attachments:a}=lt(t);for(let t of a){if(!this.fileReader){await this.sendText(r,`[${t.alt}] (file: ${t.path})`);continue}try{let n=await this.fileReader(e,t.path);if(!n||n.size===0)throw Error(`Attachment file is empty or unavailable.`);await this.sendAttachment(r,n,t)}catch(e){console.warn(`iMessage attachment send failed for ${t.path}:`,e),await this.sendText(r,`[${t.alt}] (file: ${t.path})`)}}let o=i.trim();o&&await this.sendText(r,o)}async sendAttachment(e,t,n){if(await this.ensureApiMode()===`beeper-desktop`){await this.sendAttachmentViaBeeperDesktop(e,t,n);return}await this.sendAttachmentViaLegacyBridge(e,t,n)}async sendAttachmentViaBeeperDesktop(e,t,n){let r=n.path.split(`/`).pop()||`attachment.bin`,i=new FormData;i.append(`file`,t,r),i.append(`fileName`,r),t.type&&i.append(`mimeType`,t.type);let a=`${(await this.requestJson(`/v1/assets/upload`,{method:`POST`,body:i})).uploadID||``}`.trim();if(!a)throw Error(`Beeper asset upload failed: missing uploadID`);await this.requestJson(`/v1/chats/${encodeURIComponent(e)}/messages`,{method:`POST`,body:JSON.stringify({text:n.alt||void 0,attachment:{uploadID:a,fileName:r,mimeType:t.type||void 0}})})}async sendAttachmentViaLegacyBridge(e,t,n){let r=n.path.split(`/`).pop()||`attachment.bin`,i=new FormData;i.append(`chatId`,e),n.alt&&i.append(`text`,n.alt),i.append(`file`,t,r),await this.requestJson(`/messages/send`,{method:`POST`,body:i})}async sendText(e,t){if(await this.ensureApiMode()===`beeper-desktop`){await this.requestJson(`/v1/chats/${encodeURIComponent(e)}/messages`,{method:`POST`,body:JSON.stringify({text:t})});return}await this.requestJson(`/messages/send`,{method:`POST`,body:JSON.stringify({chatId:e,text:t})})}};function ot(e){return e.trim().replace(/\/+$/,``)}function st(e){if(typeof e==`number`&&Number.isFinite(e))return e>0xe8d4a51000?e:e*1e3;if(typeof e==`string`){let t=Number(e);if(Number.isFinite(t))return st(t);let n=Date.parse(e);if(Number.isFinite(n))return n}return Date.now()}function ct(e){return new Promise(t=>setTimeout(t,e))}function lt(e){let t=[],n=/!?\[([^\]]*)\]\(([^)]+)\)/g,r=null,i=e;for(;(r=n.exec(e))!==null;){let e=r[1]||``,n=ut((r[2]||``).trim());n&&(t.push({alt:e,path:n}),i=i.replace(r[0],``))}return{remainingText:i,attachments:t}}function ut(e){if(!e)return null;let t=e.trim();if(/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(t)||t.startsWith(`//`))return null;let n=t.replace(/\\/g,`/`).replace(/^\/+/,``).replace(/^\.\//,``);if(!n)return null;let r=n.split(`/`).filter(Boolean);return r.some(e=>e===`..`)?null:r.join(`/`)}var dt=class{messageCallback=null;running=!1;type=`room`;typingCallback=null;_manager=null;deliverInbound(e){this.messageCallback?.(e)}onMessage(e){this.messageCallback=e}onTyping(e){this.typingCallback=e}setManager(e){this._manager=e}setTyping(e,t){}start(){this.running=!0}stop(){this.running=!1}async send(e,t,n){if(!this._manager)return;let r=_e(e);this._manager.broadcast(r,t,n)}};const ft=1e3;var pt=class{abortController=null;fileReader=null;messageCallback=null;offset=0;pollRetryDelayMs=ft;pollSessionId=0;registeredChatIds=new Set;running=!1;token=``;type=`telegram`;useProxy=!1;buildFileUrl(e){let t=e.split(`/`).filter(Boolean).map(e=>encodeURIComponent(e)).join(`/`);return`${this.useProxy?`/telegram/file/bot`:`https://api.telegram.org/file/bot`}${this.token}/${t}`}buildMethodUrl(t){let n=t.replace(/^\/+/,``);return`${this.useProxy?e:c}${this.token}/${n}`}configure(e,t,n=!1){this.token=e.trim(),this.registeredChatIds=new Set(t.map(e=>e.trim()).filter(Boolean)),this.useProxy=!!n}isConfigured(){return this.token.length>0}nextPollRetryDelay(){let e=this.pollRetryDelayMs;return this.pollRetryDelayMs=Math.min(this.pollRetryDelayMs*2,6e4),e}onMessage(e){this.messageCallback=e}registerChatId(e){let t=e.trim();t&&this.registeredChatIds.add(t)}resetPollBackoff(){this.pollRetryDelayMs=ft}setTyping(e,t){if(!t)return;let n=e.replace(/^tg:/,``);this.apiCall(`sendChatAction`,{chat_id:n,action:`typing`}).catch(()=>{})}start(){if(!this.token||this.running)return;this.running=!0,this.resetPollBackoff();let e=++this.pollSessionId,t=new AbortController;this.abortController=t,this.poll(e,t)}stop(){this.running=!1,this.resetPollBackoff(),this.pollSessionId+=1,this.abortController?.abort(),this.abortController=null}async apiCall(e,t){let n=await fetch(this.buildMethodUrl(e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let t=await n.text();throw Error(`Telegram API ${e} failed: ${n.status} ${t}`)}return await n.json()}async extractAttachments(e){let t=[],n=Array.isArray(e.photo)?e.photo.at(-1):null;n?.file_id&&t.push({id:n.file_id,fileName:`photo-${e.message_id}.png`,mimeType:`image/png`,previewDisposition:`inline`}),e.document?.file_id&&t.push({id:e.document.file_id,fileName:e.document.file_name||`document-${e.message_id}`,mimeType:e.document.mime_type}),e.video?.file_id&&t.push({id:e.video.file_id,fileName:e.video.file_name||`video-${e.message_id}.mp4`,mimeType:e.video.mime_type||`video/mp4`}),e.audio?.file_id&&t.push({id:e.audio.file_id,fileName:e.audio.file_name||`audio-${e.message_id}.mp3`,mimeType:e.audio.mime_type||`audio/mpeg`}),e.voice?.file_id&&t.push({id:e.voice.file_id,fileName:`voice-${e.message_id}.ogg`,mimeType:e.voice.mime_type||`audio/ogg`}),e.animation?.file_id&&t.push({id:e.animation.file_id,fileName:e.animation.file_name||`animation-${e.message_id}.mp4`,mimeType:e.animation.mime_type||`video/mp4`}),e.sticker?.file_id&&t.push({id:e.sticker.file_id,fileName:`sticker-${e.message_id}.${gt(e.sticker)}`,mimeType:e.sticker.is_animated?`application/x-tgsticker`:e.sticker.is_video?`video/webm`:`image/webp`});let r=[];for(let e of t){let t=await this.fetchTelegramFileInfo(e.id);r.push({id:e.id,fileName:e.fileName,mimeType:e.mimeType,size:t.file_size,previewDisposition:e.previewDisposition,source:{kind:`remote-url`,url:this.buildFileUrl(t.file_path)}})}return r}async fetchTelegramFileInfo(e){let t=await this.apiCall(`getFile`,{file_id:e});if(!t.ok||!t.result?.file_path)throw Error(`Telegram getFile failed for attachment ${e}`);return t.result}async handleUpdate(e){let t=e.message;if(!t)return;let n=String(t.chat.id);if(t.text===`/chatid`){this.apiCall(`sendMessage`,{chat_id:n,text:`Chat ID: ${n}\nRegister this ID in ShadowClaw settings.`}).catch(console.error);return}if(t.text===`/ping`){this.apiCall(`sendMessage`,{chat_id:n,text:`Pong! ShadowClaw is running.`}).catch(console.error);return}if(!this.registeredChatIds.has(n))return;let r=await this.extractAttachments(t),i=`${t.text||t.caption||``}`.trim()||(t.photo?.length?`[Photo]`:null)||(t.voice?`[Voice message]`:null)||(t.video?`[Video]`:null)||(t.audio?`[Audio]`:null)||(t.animation?`[Animation]`:null)||(t.document?`[Document: ${t.document.file_name||`unnamed`}]`:null)||(t.sticker?`[Sticker: ${t.sticker.emoji||``}]`:null)||(t.location?`[Location: ${t.location.latitude}, ${t.location.longitude}]`:null)||(t.contact?`[Contact: ${t.contact.first_name}]`:null)||`[Unsupported message type]`,a=t.from?.first_name||t.from?.username||String(t.from?.id||`Unknown`),o={id:String(t.message_id),groupId:`tg:${n}`,sender:a,content:i,timestamp:t.date*1e3,channel:`telegram`,attachments:r};this.messageCallback?.(o)}async poll(e,t){for(;this.running&&this.pollSessionId===e&&!t.signal.aborted;)try{let e=await fetch(this.buildMethodUrl(`getUpdates?offset=${this.offset}&timeout=30`),{signal:t.signal});if(!e.ok){console.error(`Telegram poll error: HTTP ${e.status}`),await this.waitForRetry(this.nextPollRetryDelay());continue}let n=await e.json();if(!n.ok||!Array.isArray(n.result)){await this.waitForRetry(this.nextPollRetryDelay());continue}this.resetPollBackoff();for(let e of n.result)this.offset=e.update_id+1,await this.handleUpdate(e)}catch(e){if(e instanceof Error&&e.name===`AbortError`)break;console.error(`Telegram poll error:`,e),await this.waitForRetry(this.nextPollRetryDelay())}}async send(e,n,r){let i=e.replace(/^tg:/,``),{remainingText:a,attachments:o}=_t(n);for(let t of o){if(this.fileReader)try{let n=await this.fileReader(e,t.path);if(n&&n.size>0){let e=t.path.toLowerCase();e.endsWith(`.png`)||e.endsWith(`.jpg`)||e.endsWith(`.jpeg`)||e.endsWith(`.gif`)||e.endsWith(`.webp`)?await this.sendPhoto(i,n,t.alt,t.path):await this.sendDocument(i,n,t.alt,t.path);continue}}catch(e){console.warn(`TelegramChannel: failed to read file ${t.path}:`,e)}await this.apiCall(`sendMessage`,{chat_id:i,text:`[${t.alt}] (file: ${t.path})`})}let s=a.trim();if(s){let e=mt(s,t);for(let t of e)await this.apiCall(`sendMessage`,{chat_id:i,text:t})}}async sendDocument(e,t,n,r){let i=r.split(`/`).pop()||`document.file`,a=new FormData;a.append(`chat_id`,e),a.append(`document`,t,i),n&&a.append(`caption`,n);let o=await fetch(this.buildMethodUrl(`sendDocument`),{method:`POST`,body:a});if(!o.ok){let e=await o.text();throw Error(`Telegram sendDocument failed: ${o.status} ${e}`)}}async sendPhoto(e,t,n,r){let i=r.split(`/`).pop()||`image.png`,a=new FormData;a.append(`chat_id`,e),a.append(`photo`,t,i),n&&a.append(`caption`,n);let o=await fetch(this.buildMethodUrl(`sendPhoto`),{method:`POST`,body:a});if(!o.ok){let e=await o.text();throw Error(`Telegram sendPhoto failed: ${o.status} ${e}`)}}async waitForRetry(e){await ht(e)}};function mt(e,t){if(e.length<=t)return[e];let n=[],r=e;for(;r.length>0;){if(r.length<=t){n.push(r);break}let e=t,i=r.lastIndexOf(`
|
|
1
|
+
import{D as e,E as t,F as n,I as r,M as i,O as a,P as o,R as s,T as c,_ as l,g as u,j as d,l as f,o as p,r as m,s as h,t as g,v as _,w as v}from"./config-CrHchneq.js";import{n as y,r as b}from"./txPromise-EBECky1b.js";import{t as x}from"./getConfig-D89uJgo5.js";import{p as S}from"./custom-element-security-NCqQ5lmC.js";import{n as C}from"./toast-60iDlgiH.js";import{At as w,C as T,Ct as E,Dt as ee,En as te,Et as ne,Ft as D,G as O,Gt as k,H as A,Ht as j,I as M,It as N,Jt as P,Kt as F,Lt as I,M as re,Mt as ie,N as L,Nt as R,On as ae,Ot as z,P as oe,Pt as se,St as B,Tn as ce,Tt as le,U as V,Ut as ue,V as de,W as fe,Wt as pe,X as me,Xt as he,Y as ge,Yt as _e,_n as ve,an as ye,at as be,bn as xe,bt as Se,dn as H,dt as Ce,fn as we,ft as Te,gn as Ee,gt as De,hn as Oe,in as ke,j as Ae,jt as je,kt as U,l as Me,ln as Ne,mn as W,on as Pe,ot as Fe,pn as G,qt as Ie,rn as K,t as q,u as Le,un as Re,ut as ze,vn as Be,yn as Ve}from"./orchestrator-tHWrqi_F.js";import{l as He,r as Ue}from"./getGroupDir-P1h9wl6S.js";import{t as J}from"./setConfig-DFMYnYLE.js";import{t as Y}from"./ulid-BY7rQVLN.js";import{a as We,o as Ge,r as Ke,s as qe}from"./syncWebMcpRegistration-DzC80wVG.js";import{n as Je,r as Ye}from"./crypto-C8c5wMzN.js";import{a as Xe,i as Ze,r as X,t as Qe}from"./peerjs-CuSJUH-r.js";async function $e(e){if(!(!e||e.name===`shadowclaw`)){try{if(await x(e,m.DB_MIGRATED_FROM_LEGACY)===`true`)return}catch{}try{let t=await new Promise(e=>{let t=indexedDB.open(l);t.onsuccess=()=>{let n=t.result;if(!n.objectStoreNames||n.objectStoreNames.length===0){n.close(),e(null);return}e(n)},t.onerror=()=>e(null)});if(t){let n=Array.from(t.objectStoreNames).filter(t=>e.objectStoreNames.contains(t));for(let r of n)await new Promise(n=>{try{let i=t.transaction(r,`readonly`).objectStore(r).getAll();i.onsuccess=()=>{let t=i.result||[];if(t.length>0)try{let i=e.transaction(r,`readwrite`),a=i.objectStore(r);for(let e of t)a.put(e);i.oncomplete=()=>n(),i.onerror=()=>n(),i.onabort=()=>n()}catch{n()}else n()},i.onerror=()=>n()}catch{n()}});t.close()}}catch(e){console.warn(`Legacy IndexedDB migration warning:`,e)}finally{try{await J(e,m.DB_MIGRATED_FROM_LEGACY,`true`)}catch{}}}}async function et(e,t,n){for await(let[r,i]of e.entries())if(i.kind===`directory`)await et(i,await t.getDirectoryHandle(r,{create:!0}),[...n,r]);else if(i.kind===`file`){let e=await i.getFile(),a=await t.getFileHandle(r,{create:!0});try{await Ne(a,e)}catch(t){if(!(t instanceof Error?t.message:String(t)).includes(`Writable file streams are not supported`))throw t;await Re([...n,r],e)}}}async function tt(e){if(!e)return;try{if(await x(e,m.OPFS_MIGRATED_FROM_LEGACY)===`true`)return}catch{}let t=Ue();if(t!==`shadowclaw`&&!(typeof navigator>`u`||!navigator.storage||typeof navigator.storage.getDirectory!=`function`))try{let n=await navigator.storage.getDirectory(),r;try{r=await n.getDirectoryHandle(_)}catch{try{await J(e,m.OPFS_MIGRATED_FROM_LEGACY,`true`)}catch{}return}let i=await n.getDirectoryHandle(t,{create:!0});await et(r,i,[t])}catch(e){console.warn(`Legacy OPFS migration warning:`,e)}finally{try{await J(e,m.OPFS_MIGRATED_FROM_LEGACY,`true`)}catch{}}}function nt(){return new Promise(async(e,t)=>{let n,r=d(),i=indexedDB.open(r,2);i.onupgradeneeded=()=>{let e=i.result;if(!e.objectStoreNames.contains(`messages`)){let t=e.createObjectStore(`messages`,{keyPath:`id`});t.createIndex(`by-group-time`,[`groupId`,`timestamp`]),t.createIndex(`by-group`,`groupId`)}if(e.objectStoreNames.contains(`sessions`)||e.createObjectStore(`sessions`,{keyPath:`groupId`}),!e.objectStoreNames.contains(`tasks`)){let t=e.createObjectStore(`tasks`,{keyPath:`id`});t.createIndex(`by-group`,`groupId`),t.createIndex(`by-enabled`,`enabled`)}e.objectStoreNames.contains(`config`)||e.createObjectStore(`config`,{keyPath:`key`}),e.objectStoreNames.contains(`pendingShares`)||e.createObjectStore(`pendingShares`,{keyPath:`id`}).createIndex(`by-createdAt`,`createdAt`)},i.onsuccess=async()=>{n=i.result,b(n);try{await $e(n),await tt(n)}catch(e){console.warn(`Error running legacy migration:`,e)}e(n)},i.onerror=()=>{t(Error(`Failed to open IndexedDB: ${i.error?.message}`))}})}var rt=class{activeGroupId;displayCallback;messageCallback;type;typingCallback;constructor(){this.type=`browser`,this.messageCallback=null,this.typingCallback=null,this.displayCallback=null,this.activeGroupId=p}getActiveGroup(){return this.activeGroupId}onDisplay(e){this.displayCallback=e}onMessage(e){this.messageCallback=e}onTyping(e){this.typingCallback=e}setActiveGroup(e){this.activeGroupId=e}setTyping(e,t){this.typingCallback?.(e,t)}start(){}stop(){}submit(e,t,n=[],r,i,a){let o=t||this.activeGroupId,s={id:Y(),groupId:o,sender:`You`,content:e,timestamp:Date.now(),channel:`browser`,attachments:n,a2uiAction:r,freshContext:i,subagent:a};this.messageCallback?.(s)}async send(e,t,n){this.displayCallback?.(e,t,!0)}},it=class{_entries;constructor(){this._entries=[]}find(e){return this.resolve(e)?.channel??null}get(e){return this._entries.find(t=>t.prefix===e)?.channel}getBadge(e){return this.resolve(e)?.badge??``}getChannelType(e){return this.resolve(e)?.channel.type??null}onMessage(e){for(let t of this._entries)t.channel.onMessage(e)}onTyping(e){for(let t of this._entries)t.channel.onTyping&&t.channel.onTyping(e)}prefixes(){return this._entries.map(e=>e.prefix)}register(e,t,n){let r=typeof n==`string`?{badge:n}:n??{};this._entries.push({prefix:e,channel:t,badge:r.badge??e.replace(/:$/,``),autoTrigger:r.autoTrigger??!1}),this._entries.sort((e,t)=>t.prefix.length-e.prefix.length)}resolve(e){for(let t of this._entries)if(e.startsWith(t.prefix))return t;return null}shouldAutoTrigger(e){return this.resolve(e)?.autoTrigger??!1}startAll(){for(let e of this._entries)e.channel.start()}stopAll(){for(let e of this._entries)e.channel.stop()}},at=class{abortController=null;apiKey=``;apiMode=`unknown`;cursor=null;fileReader=null;messageCallback=null;reconnectDelayMs=1e3;registeredChatIds=new Set;running=!1;seenMessageIds=new Map;serverUrl=``;type=`imessage`;configure(e,t,n){this.serverUrl=ot(e),this.apiKey=t.trim(),this.registeredChatIds=new Set(n.map(e=>e.trim()).filter(Boolean)),this.cursor=null,this.apiMode=`unknown`}handleIncomingMessage(e){this.pruneSeenMessageIds();let t=String(e.chatId||e.conversationId||``).trim();if(!t||this.registeredChatIds.size>0&&!this.registeredChatIds.has(t))return;let n=`${e.text||e.body||``}`.trim();if(!n)return;let r=`${e.id||e.guid||`${t}:${e.timestamp||e.createdAt||n}`}`;if(this.seenMessageIds.has(r))return;this.seenMessageIds.set(r,Date.now());let i={id:r,groupId:`im:${t}`,sender:`${e.sender||e.handle||e.from||`iMessage`}`,content:n,timestamp:st(e.timestamp||e.createdAt),channel:`imessage`};this.messageCallback?.(i)}handlePollResponse(e){e.nextCursor!==void 0&&e.nextCursor!==null?this.cursor=String(e.nextCursor):e.cursor!==void 0&&e.cursor!==null&&(this.cursor=String(e.cursor));let t=Array.isArray(e.messages)?e.messages:[];for(let e of t)this.handleIncomingMessage(e)}isConfigured(){return this.serverUrl.length>0}onMessage(e){this.messageCallback=e}pruneSeenMessageIds(){let e=Date.now();for(let[t,n]of this.seenMessageIds.entries())e-n>6e4&&this.seenMessageIds.delete(t)}setTyping(e,t){if(!t)return;let n=e.replace(/^im:/,``);this.requestJson(`/messages/typing`,{method:`POST`,body:JSON.stringify({chatId:n,typing:!0})}).catch(()=>{})}start(){!this.isConfigured()||this.running||(this.running=!0,this.abortController=new AbortController,this.poll())}stop(){this.running=!1,this.abortController?.abort(),this.abortController=null}async ensureApiMode(){if(this.apiMode!==`unknown`)return this.apiMode;try{await this.requestJson(`/v1/info`,{method:`GET`}),this.apiMode=`beeper-desktop`}catch{this.apiMode=`legacy`}return this.apiMode}async poll(){for(;this.running&&this.abortController&&!this.abortController.signal.aborted;)try{let e=new URLSearchParams({timeout:`25`});this.cursor&&e.set(`cursor`,this.cursor);let t=await this.requestJson(`/messages?${e.toString()}`,{method:`GET`},u+5e3,this.abortController.signal);this.reconnectDelayMs=1e3,this.handlePollResponse(t)}catch(e){if(e instanceof Error&&e.name===`AbortError`)break;console.error(`iMessage bridge poll error:`,e),await ct(this.reconnectDelayMs),this.reconnectDelayMs=Math.min(this.reconnectDelayMs*2,3e4)}}async requestJson(e,t,n=u,r){let i=new AbortController,a=setTimeout(()=>i.abort(),n),o=()=>i.abort();r?.addEventListener(`abort`,o,{once:!0});try{let n=new Headers(t.headers);n.set(`Accept`,`application/json`),!n.has(`Content-Type`)&&t.body&&!(t.body instanceof FormData)&&n.set(`Content-Type`,`application/json`),this.apiKey&&(n.set(`Authorization`,`Bearer ${this.apiKey}`),n.set(`X-API-Key`,this.apiKey));let r=await fetch(`${this.serverUrl}${e}`,{...t,headers:n,signal:i.signal});if(!r.ok){let e=await r.text();throw Error(`iMessage bridge request failed: ${r.status} ${e}`)}return r.status===204?{messages:[]}:await r.json()}finally{clearTimeout(a),r?.removeEventListener(`abort`,o)}}async send(e,t,n){let r=e.replace(/^im:/,``),{remainingText:i,attachments:a}=lt(t);for(let t of a){if(!this.fileReader){await this.sendText(r,`[${t.alt}] (file: ${t.path})`);continue}try{let n=await this.fileReader(e,t.path);if(!n||n.size===0)throw Error(`Attachment file is empty or unavailable.`);await this.sendAttachment(r,n,t)}catch(e){console.warn(`iMessage attachment send failed for ${t.path}:`,e),await this.sendText(r,`[${t.alt}] (file: ${t.path})`)}}let o=i.trim();o&&await this.sendText(r,o)}async sendAttachment(e,t,n){if(await this.ensureApiMode()===`beeper-desktop`){await this.sendAttachmentViaBeeperDesktop(e,t,n);return}await this.sendAttachmentViaLegacyBridge(e,t,n)}async sendAttachmentViaBeeperDesktop(e,t,n){let r=n.path.split(`/`).pop()||`attachment.bin`,i=new FormData;i.append(`file`,t,r),i.append(`fileName`,r),t.type&&i.append(`mimeType`,t.type);let a=`${(await this.requestJson(`/v1/assets/upload`,{method:`POST`,body:i})).uploadID||``}`.trim();if(!a)throw Error(`Beeper asset upload failed: missing uploadID`);await this.requestJson(`/v1/chats/${encodeURIComponent(e)}/messages`,{method:`POST`,body:JSON.stringify({text:n.alt||void 0,attachment:{uploadID:a,fileName:r,mimeType:t.type||void 0}})})}async sendAttachmentViaLegacyBridge(e,t,n){let r=n.path.split(`/`).pop()||`attachment.bin`,i=new FormData;i.append(`chatId`,e),n.alt&&i.append(`text`,n.alt),i.append(`file`,t,r),await this.requestJson(`/messages/send`,{method:`POST`,body:i})}async sendText(e,t){if(await this.ensureApiMode()===`beeper-desktop`){await this.requestJson(`/v1/chats/${encodeURIComponent(e)}/messages`,{method:`POST`,body:JSON.stringify({text:t})});return}await this.requestJson(`/messages/send`,{method:`POST`,body:JSON.stringify({chatId:e,text:t})})}};function ot(e){return e.trim().replace(/\/+$/,``)}function st(e){if(typeof e==`number`&&Number.isFinite(e))return e>0xe8d4a51000?e:e*1e3;if(typeof e==`string`){let t=Number(e);if(Number.isFinite(t))return st(t);let n=Date.parse(e);if(Number.isFinite(n))return n}return Date.now()}function ct(e){return new Promise(t=>setTimeout(t,e))}function lt(e){let t=[],n=/!?\[([^\]]*)\]\(([^)]+)\)/g,r=null,i=e;for(;(r=n.exec(e))!==null;){let e=r[1]||``,n=ut((r[2]||``).trim());n&&(t.push({alt:e,path:n}),i=i.replace(r[0],``))}return{remainingText:i,attachments:t}}function ut(e){if(!e)return null;let t=e.trim();if(/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(t)||t.startsWith(`//`))return null;let n=t.replace(/\\/g,`/`).replace(/^\/+/,``).replace(/^\.\//,``);if(!n)return null;let r=n.split(`/`).filter(Boolean);return r.some(e=>e===`..`)?null:r.join(`/`)}var dt=class{messageCallback=null;running=!1;type=`room`;typingCallback=null;_manager=null;deliverInbound(e){this.messageCallback?.(e)}onMessage(e){this.messageCallback=e}onTyping(e){this.typingCallback=e}setManager(e){this._manager=e}setTyping(e,t){}start(){this.running=!0}stop(){this.running=!1}async send(e,t,n){if(!this._manager)return;let r=_e(e);this._manager.broadcast(r,t,n)}};const ft=1e3;var pt=class{abortController=null;fileReader=null;messageCallback=null;offset=0;pollRetryDelayMs=ft;pollSessionId=0;registeredChatIds=new Set;running=!1;token=``;type=`telegram`;useProxy=!1;buildFileUrl(e){let t=e.split(`/`).filter(Boolean).map(e=>encodeURIComponent(e)).join(`/`);return`${this.useProxy?`/telegram/file/bot`:`https://api.telegram.org/file/bot`}${this.token}/${t}`}buildMethodUrl(t){let n=t.replace(/^\/+/,``);return`${this.useProxy?e:c}${this.token}/${n}`}configure(e,t,n=!1){this.token=e.trim(),this.registeredChatIds=new Set(t.map(e=>e.trim()).filter(Boolean)),this.useProxy=!!n}isConfigured(){return this.token.length>0}nextPollRetryDelay(){let e=this.pollRetryDelayMs;return this.pollRetryDelayMs=Math.min(this.pollRetryDelayMs*2,6e4),e}onMessage(e){this.messageCallback=e}registerChatId(e){let t=e.trim();t&&this.registeredChatIds.add(t)}resetPollBackoff(){this.pollRetryDelayMs=ft}setTyping(e,t){if(!t)return;let n=e.replace(/^tg:/,``);this.apiCall(`sendChatAction`,{chat_id:n,action:`typing`}).catch(()=>{})}start(){if(!this.token||this.running)return;this.running=!0,this.resetPollBackoff();let e=++this.pollSessionId,t=new AbortController;this.abortController=t,this.poll(e,t)}stop(){this.running=!1,this.resetPollBackoff(),this.pollSessionId+=1,this.abortController?.abort(),this.abortController=null}async apiCall(e,t){let n=await fetch(this.buildMethodUrl(e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let t=await n.text();throw Error(`Telegram API ${e} failed: ${n.status} ${t}`)}return await n.json()}async extractAttachments(e){let t=[],n=Array.isArray(e.photo)?e.photo.at(-1):null;n?.file_id&&t.push({id:n.file_id,fileName:`photo-${e.message_id}.png`,mimeType:`image/png`,previewDisposition:`inline`}),e.document?.file_id&&t.push({id:e.document.file_id,fileName:e.document.file_name||`document-${e.message_id}`,mimeType:e.document.mime_type}),e.video?.file_id&&t.push({id:e.video.file_id,fileName:e.video.file_name||`video-${e.message_id}.mp4`,mimeType:e.video.mime_type||`video/mp4`}),e.audio?.file_id&&t.push({id:e.audio.file_id,fileName:e.audio.file_name||`audio-${e.message_id}.mp3`,mimeType:e.audio.mime_type||`audio/mpeg`}),e.voice?.file_id&&t.push({id:e.voice.file_id,fileName:`voice-${e.message_id}.ogg`,mimeType:e.voice.mime_type||`audio/ogg`}),e.animation?.file_id&&t.push({id:e.animation.file_id,fileName:e.animation.file_name||`animation-${e.message_id}.mp4`,mimeType:e.animation.mime_type||`video/mp4`}),e.sticker?.file_id&&t.push({id:e.sticker.file_id,fileName:`sticker-${e.message_id}.${gt(e.sticker)}`,mimeType:e.sticker.is_animated?`application/x-tgsticker`:e.sticker.is_video?`video/webm`:`image/webp`});let r=[];for(let e of t){let t=await this.fetchTelegramFileInfo(e.id);r.push({id:e.id,fileName:e.fileName,mimeType:e.mimeType,size:t.file_size,previewDisposition:e.previewDisposition,source:{kind:`remote-url`,url:this.buildFileUrl(t.file_path)}})}return r}async fetchTelegramFileInfo(e){let t=await this.apiCall(`getFile`,{file_id:e});if(!t.ok||!t.result?.file_path)throw Error(`Telegram getFile failed for attachment ${e}`);return t.result}async handleUpdate(e){let t=e.message;if(!t)return;let n=String(t.chat.id);if(t.text===`/chatid`){this.apiCall(`sendMessage`,{chat_id:n,text:`Chat ID: ${n}\nRegister this ID in ShadowClaw settings.`}).catch(console.error);return}if(t.text===`/ping`){this.apiCall(`sendMessage`,{chat_id:n,text:`Pong! ShadowClaw is running.`}).catch(console.error);return}if(!this.registeredChatIds.has(n))return;let r=await this.extractAttachments(t),i=`${t.text||t.caption||``}`.trim()||(t.photo?.length?`[Photo]`:null)||(t.voice?`[Voice message]`:null)||(t.video?`[Video]`:null)||(t.audio?`[Audio]`:null)||(t.animation?`[Animation]`:null)||(t.document?`[Document: ${t.document.file_name||`unnamed`}]`:null)||(t.sticker?`[Sticker: ${t.sticker.emoji||``}]`:null)||(t.location?`[Location: ${t.location.latitude}, ${t.location.longitude}]`:null)||(t.contact?`[Contact: ${t.contact.first_name}]`:null)||`[Unsupported message type]`,a=t.from?.first_name||t.from?.username||String(t.from?.id||`Unknown`),o={id:String(t.message_id),groupId:`tg:${n}`,sender:a,content:i,timestamp:t.date*1e3,channel:`telegram`,attachments:r};this.messageCallback?.(o)}async poll(e,t){for(;this.running&&this.pollSessionId===e&&!t.signal.aborted;)try{let e=await fetch(this.buildMethodUrl(`getUpdates?offset=${this.offset}&timeout=30`),{signal:t.signal});if(!e.ok){console.error(`Telegram poll error: HTTP ${e.status}`),await this.waitForRetry(this.nextPollRetryDelay());continue}let n=await e.json();if(!n.ok||!Array.isArray(n.result)){await this.waitForRetry(this.nextPollRetryDelay());continue}this.resetPollBackoff();for(let e of n.result)this.offset=e.update_id+1,await this.handleUpdate(e)}catch(e){if(e instanceof Error&&e.name===`AbortError`)break;console.error(`Telegram poll error:`,e),await this.waitForRetry(this.nextPollRetryDelay())}}async send(e,n,r){let i=e.replace(/^tg:/,``),{remainingText:a,attachments:o}=_t(n);for(let t of o){if(this.fileReader)try{let n=await this.fileReader(e,t.path);if(n&&n.size>0){let e=t.path.toLowerCase();e.endsWith(`.png`)||e.endsWith(`.jpg`)||e.endsWith(`.jpeg`)||e.endsWith(`.gif`)||e.endsWith(`.webp`)?await this.sendPhoto(i,n,t.alt,t.path):await this.sendDocument(i,n,t.alt,t.path);continue}}catch(e){console.warn(`TelegramChannel: failed to read file ${t.path}:`,e)}await this.apiCall(`sendMessage`,{chat_id:i,text:`[${t.alt}] (file: ${t.path})`})}let s=a.trim();if(s){let e=mt(s,t);for(let t of e)await this.apiCall(`sendMessage`,{chat_id:i,text:t})}}async sendDocument(e,t,n,r){let i=r.split(`/`).pop()||`document.file`,a=new FormData;a.append(`chat_id`,e),a.append(`document`,t,i),n&&a.append(`caption`,n);let o=await fetch(this.buildMethodUrl(`sendDocument`),{method:`POST`,body:a});if(!o.ok){let e=await o.text();throw Error(`Telegram sendDocument failed: ${o.status} ${e}`)}}async sendPhoto(e,t,n,r){let i=r.split(`/`).pop()||`image.png`,a=new FormData;a.append(`chat_id`,e),a.append(`photo`,t,i),n&&a.append(`caption`,n);let o=await fetch(this.buildMethodUrl(`sendPhoto`),{method:`POST`,body:a});if(!o.ok){let e=await o.text();throw Error(`Telegram sendPhoto failed: ${o.status} ${e}`)}}async waitForRetry(e){await ht(e)}};function mt(e,t){if(e.length<=t)return[e];let n=[],r=e;for(;r.length>0;){if(r.length<=t){n.push(r);break}let e=t,i=r.lastIndexOf(`
|
|
2
2
|
`,t);i>t*.5&&(e=i),n.push(r.slice(0,e)),r=r.slice(e)}return n}function ht(e){return new Promise(t=>setTimeout(t,e))}function gt(e){return e?.is_animated?`tgs`:e?.is_video?`webm`:`webp`}function _t(e){let t=[],n=/!?\[([^\]]*)\]\(([^)]+)\)/g,r,i=e;for(;(r=n.exec(e))!==null;){let e=r[1],n=vt((r[2]||``).trim());n&&(t.push({alt:e,path:n}),i=i.replace(r[0],``))}return{remainingText:i,attachments:t}}function vt(e){if(!e)return null;let t=e.trim();if(/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(t)||t.startsWith(`//`))return null;let n=t.replace(/\\/g,`/`).replace(/^\/+/,``).replace(/^\.\//,``);if(!n)return null;let r=n.split(`/`).filter(Boolean);return r.some(e=>e===`..`)?null:r.join(`/`)}function yt(e,t){let n=JSON.stringify(e.dataModel??{},null,2),r=t?`${t}`:`The user`;return`[A2UI ACTION]\nsurfaceId: "${e.surfaceId}"\nactionId: "${e.actionId}"\n`+(t?`firedBy: "${t}"\n`:``)+`dataModel:\n${n}\n\nInstructions: ${r} triggered the "${e.actionId}" action on surface "${e.surfaceId}". The dataModel above contains the current form values. Use the appropriate tool(s) to fulfill the action based on the actionId and dataModel values. After you have a result, call render_component with action "updateDataModel" on surfaceId "${e.surfaceId}" to update the surface (e.g. set path "/result" to the output value). Do NOT respond with plain text only — always update the surface via render_component.`}var bt=class{static formatMessagesXml(e){let t=e=>e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`);return`<messages>\n${e.map(e=>`<message sender="${t(e.sender)}" time="${new Date(e.timestamp).toISOString()}">${t(e.content)}</message>`).join(`
|
|
3
3
|
`)}\n</messages>`}static formatOutbound(e){return e.replace(/<internal>[\s\S]*?<\/internal>/g,``).trim()}registry;constructor(e){this.registry=e}findChannel(e){return this.registry.find(e)}setTyping(e,t){this.findChannel(e)?.setTyping(e,t)}async send(e,t,n){let r=this.findChannel(e);if(!r){console.warn(`No channel for groupId: ${e}`);return}await r.send(e,t,n)}};const xt={"litert-community/gemma-4-E2B-it-litert-lm":`https://huggingface.co/litert-community/gemma-4-E2B-it-litert-lm/resolve/main/gemma-4-E2B-it-web.litertlm`,"litert-community/gemma-4-E4B-it-litert-lm":`https://huggingface.co/litert-community/gemma-4-E4B-it-litert-lm/resolve/main/gemma-4-E4B-it-web.litertlm`},St=Object.keys(xt);function Ct(){return typeof navigator<`u`&&`gpu`in navigator&&typeof WebAssembly<`u`&&`Suspending`in WebAssembly}let wt=null,Tt=null,Et=null,Dt=null;const Ot=k;async function kt(e,t,n){return pe(e,t,n,{cacheName:`shadow-claw-litertlm-models`,chunkSize:Ot})}async function At(e,t,n){if(Tt===e&&wt)return wt;if(Et&&Dt===e)return Et;Dt=e,Et=(async()=>{if(wt){try{await wt.delete?.()}catch{}wt=null,Tt=null}let r=xt[e];if(!r)throw Error(`LiteRT-LM: Model '${e} is not supported. Supported models: ${St.join(`, `)}`);let i=await import(`./dist-DUy1CvmT.js`).catch(()=>{throw Error(`LiteRT-LM: The @litert-lm/core package is not installed. Run: npm install @litert-lm/core`)}),a=i.Engine??i.default?.Engine;if(typeof a?.create!=`function`)throw Error(`LiteRT-LM: Could not locate Engine.create in @litert-lm/core. Ensure you have the latest version installed.`);let o=await kt(r,t??(()=>{}),n),s=await a.create({model:o,mainExecutorSettings:{maxNumTokens:8192}});return wt=s,Tt=e,s})();try{return await Et}finally{Et=null,Dt=null}}function jt(e){if(!e)return null;let t=e.match(/<\|tool_call>call:([A-Za-z0-9_]+)(\{[\s\S]*?)(?:<tool_call\|>|$)/);if(!t)return null;let n=t[1],r=t[2];r=r.replace(/<\|"\|>/g,`"`);function i(e){return e.replace(/([{,]\s*)([A-Za-z_$][A-Za-z0-9_$]*)(\s*:)/g,`$1"$2"$3`)}let a={},o=[r,i(r)];for(let e of o)try{let t=JSON.parse(e);if(t&&typeof t==`object`&&!Array.isArray(t)){a=t;break}}catch{}if(Object.keys(a).length===0){let e=r.indexOf(`{`),t=r.lastIndexOf(`}`);if(e>=0&&t>e){let n=r.slice(e,t+1);for(let e of[n,i(n)])try{let t=JSON.parse(e);if(t&&typeof t==`object`&&!Array.isArray(t)){a=t;break}}catch{}}}return{name:n,input:a}}function Mt(e){let t=G(String(e||``),`litert_lm`).trim();if(!t)return null;let n=e=>{try{let t=JSON.parse(e);if(t&&typeof t==`object`&&(t.type===`tool_use`||t.type===`response`))return t.tools_calls&&!t.tool_calls&&(t.tool_calls=t.tools_calls),{...t,format:`json`}}catch{}return null},r=n(t);if(r)return r;let i=t.indexOf(`{`),a=t.lastIndexOf(`}`);if(i>=0&&a>i&&(r=n(t.slice(i,a+1)),r))return r;if(t.includes(`"tool_use"`)){let e=/"name"\s*:\s*"([^"]+)"/.exec(t);if(e){let n={},r=/"input"\s*:\s*(\{.*?\})\s*(?:]|\}|"|$)/s.exec(t);if(r)try{n=JSON.parse(r[1])}catch{}return{type:`tool_use`,format:`json`,tool_calls:[{id:`litert_${Date.now()}`,name:e[1],input:n}]}}}let o=jt(t);return o?{type:`tool_use`,format:`model_specific`,tool_calls:[{id:`litert_${Date.now()}`,name:o.name,input:o.input}]}:null}function Nt(e,t,n){let r=[],i=e||``;if(n.length>0){let e=[``,`TOOL CALLING INSTRUCTIONS:`,`Return ONLY valid JSON (no markdown fences).`,`To call a tool: {"type":"tool_use","tool_calls":[{"name":"<tool>","input":{...}}]}`,`To reply: {"type":"response","response":"<your answer>"}`,`IMPORTANT: When you need to use a tool, output ONLY the JSON above — do NOT describe the call as text.`,``,`Available tools:`,n.map(e=>{let t=Object.keys(e.input_schema.properties||{}).join(`, `),n=e.description.split(`. `)[0];return`${e.name}(${t}): ${n}`}).join(`
|
|
4
4
|
`)].join(`
|