UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

1 lines • 10.1 kB
import{n as e,r as t}from"./rolldown-runtime-8BhlS34s.js";import{Pu as n,zu as r}from"./control-ui-core-CBJ5efDh.js";import{Io as i}from"./ui-CmSP4d14.js";var a;function o(){return(o=e((()=>{a=class{constructor(e,t,n=()=>1){this.capacity=e,this.overflow=t,this.measure=n,this.values=[],this.head=0,this.size=0,this.closed=!1}push(e){if(this.closed)return!1;let t=this.measure(e);if(this.size+t<=this.capacity)return this.values.push(e),this.size+=t,!0;if(this.overflow.mode!==`drop-oldest`)return this.closed=!0,this.overflow.mode===`fail-closed`&&(this.drain(),this.overflow.onOverflow()),!1;for(this.values.push(e),this.size+=t;this.size>this.capacity&&this.head<this.values.length-1;){let e=this.values[this.head];this.size-=this.measure(e),this.values[this.head]=void 0,this.head+=1}if(this.size>this.capacity){let t=this.overflow.fit?.(e,this.capacity);this.values=t===void 0?[]:[t],this.head=0,this.size=t===void 0?0:this.measure(t)}else this.head*2>=this.values.length&&(this.values=this.values.slice(this.head),this.head=0);return!0}drain(){let e=this.head===0?this.values:this.values.slice(this.head);return this.values=[],this.head=0,this.size=0,e}}})))()}function s(e){for(let t of[`sessionId`,`agentId`,`shell`,`cwd`])if(!i(e[t]))return t;return null}function c(e){let t=s(e)??(typeof e.buffer==`string`?null:`buffer`)??(typeof e.seq==`number`&&Number.isSafeInteger(e.seq)?null:`seq`);if(t)throw new _(t)}function l(e){return e instanceof Error&&/^gateway request timed out after \d+ms: (?:terminal\.open|sessions\.catalog\.startTerminal)$/u.test(e.message)}function u(e){return e instanceof Error&&(e.message===`terminal open timed out`||l(e))}var d,f,p,m,h,g,_,v;function y(){return(y=e((()=>{o(),d=2e4,f=5e3,p=2,m=5e3,h=35e3,g=class extends Error{constructor(e){super(`terminal open timed out`,{cause:e}),this.name=`TerminalOpenTimeoutError`}},_=class extends Error{constructor(e){super(`terminal session response is missing ${e}`),this.field=e,this.name=`TerminalOpenUnusableSessionError`}},v=class e{static{this.MAX_PENDING_EVENTS=512}constructor(e){this.client=e,this.streams=new Map,this.pending=new Map,this.unsubscribe=null,this.disposed=!1,this.pendingOpenCount=0,this.livenessTimer=null,this.livenessProbeInFlight=!1,this.livenessProbeFailures=0,this.lastLivenessFailureActivityVersion=null,this.lastTerminalActivityAtMs=Date.now(),this.inboundActivityVersion=0}ensureSubscribed(){this.unsubscribe||=this.client.addEventListener(e=>{if(e.event===`terminal.data`){this.noteTerminalActivity();let t=e.payload;if(t?.sessionId&&typeof t.seq==`number`&&typeof t.data==`string`){let e={kind:`data`,seq:t.seq,data:t.data},n=this.streams.get(t.sessionId);n?this.deliverData(t.sessionId,n,e):this.bufferEarly(t.sessionId,e)}return}if(e.event===`terminal.exit`){this.noteTerminalActivity();let t=e.payload;if(t?.sessionId){let e={exitCode:t.exitCode??null,signal:t.signal??null,reason:t.reason,error:t.error},n=this.streams.get(t.sessionId);n&&!n.recovering?this.deliverExit(t.sessionId,n,e):this.bufferEarly(t.sessionId,{kind:`exit`,info:e})}}})}open(e,t){return this.openRequest(`terminal.open`,e,t)}start(e,t){return this.openRequest(`sessions.catalog.startTerminal`,e,t)}async openRequest(e,t,n){let r;try{r=await this.requestWhileHoldingStream(()=>this.client.request(e,t,{timeoutMs:h}))}catch(e){throw u(e)?(l(e)&&this.forceReconnect(`terminal open watchdog timeout`),new g(e)):e}let a=s(r);if(a)throw i(r.sessionId)&&this.close(r.sessionId),new _(a);if(this.disposed)return r;let o=this.setStream(r.sessionId,n,{expectedSeq:0,recovering:!1});return this.flushPending(r.sessionId,o),this.scheduleLivenessCheck(),r}async attach(e,t){let n=await this.requestReplay(e),r=n.seq;if(this.disposed)return n;let i=this.setStream(e,t,{expectedSeq:r,recovering:!0}),a=i.abort.signal;try{await t.onReplay({data:n.buffer,newlyObservedFrom:n.buffer.length,mode:`initial`,signal:a})}catch(t){throw a.aborted||(this.removeStream(e),this.pending.delete(e),this.maybeUnsubscribe()),t}return a.aborted?n:(i.recovering=!1,this.flushPending(e,i,r),this.scheduleLivenessCheck(),n)}async list(){return(await this.client.request(`terminal.list`))?.sessions??[]}requestReplay(e){return this.requestWhileHoldingStream(async()=>{let t=await this.client.request(`terminal.attach`,{sessionId:e});return c(t),t})}async requestWhileHoldingStream(e){this.ensureSubscribed(),this.pendingOpenCount+=1;try{let t=await e();return--this.pendingOpenCount,t}catch(e){throw--this.pendingOpenCount,this.maybeUnsubscribe(),e}}deliverData(e,t,n){if(t.recovering){this.bufferEarly(e,n);return}if(!Number.isSafeInteger(n.seq)){this.recoverGap(e,t,n);return}if(n.seq-n.data.length===t.expectedSeq){t.expectedSeq=n.seq,t.sink.onData(n.data);return}this.recoverGap(e,t,n)}recoverGap(e,t,n){if(t.recovering)return;t.recovering=!0;let r=t.abort.signal;this.requestReplay(e).then(async n=>{if(r.aborted)return;let i=n.seq,a=t.expectedSeq;t.expectedSeq=i;let o=i-n.buffer.length,s=Math.max(0,Math.min(n.buffer.length,a-o));await t.sink.onReplay({data:n.buffer,newlyObservedFrom:s,mode:`recovery`,signal:r}),!r.aborted&&(t.recovering=!1,this.flushPending(e,t,i))}).catch(()=>{if(r.aborted)return;let i=this.pending.get(e)?.drain();if(i?.some(e=>e.kind===`exit`)){this.pending.delete(e),t.recovering=!1,t.sink.onData(n.data);for(let n of i)if(n.kind===`data`)t.sink.onData(n.data);else{this.deliverExit(e,t,n.info);break}return}t.recovering=!1,this.pending.delete(e),this.forceReconnect(`terminal replay failed`)})}flushPending(e,t,n){let r=this.pending.get(e);if(!r)return;this.pending.delete(e);let i=r.drain();for(let r of i){if(this.streams.get(e)!==t)break;if(n===void 0||r.kind!==`exit`||r.info.reason!==`detached`){if(r.kind===`data`){if(n!==void 0&&r.seq<=n)continue;this.deliverData(e,t,r)}else t.recovering?this.bufferEarly(e,r):this.deliverExit(e,t,r.info)}}}deliverExit(e,t,n){this.removeStream(e),t.sink.onExit(n),this.pending.delete(e),this.maybeUnsubscribe()}setStream(e,t,n){this.removeStream(e);let r={abort:new AbortController,sink:t,...n};return this.streams.set(e,r),this.lastTerminalActivityAtMs=Date.now(),r}removeStream(e){this.streams.get(e)?.abort.abort(),this.streams.delete(e)}bufferEarly(t,n){let r=this.pending.get(t)??new a(e.MAX_PENDING_EVENTS,{mode:`drop-oldest`});this.pending.set(t,r),r.push(n)}noteTerminalActivity(){this.resetLivenessProbeFailures(),this.lastTerminalActivityAtMs=Date.now(),this.inboundActivityVersion+=1}forceReconnect(e){this.resetLivenessProbeFailures(),this.client.forceReconnect(e)}resetLivenessProbeFailures(){this.livenessProbeFailures=0,this.lastLivenessFailureActivityVersion=null}scheduleLivenessCheck(e=d){this.livenessTimer||this.livenessProbeInFlight||this.streams.size===0||(this.livenessTimer=setTimeout(()=>{this.livenessTimer=null,this.checkLiveness()},Math.max(0,e)))}checkLiveness(){if(this.streams.size===0)return;let e=d-(Date.now()-this.lastTerminalActivityAtMs);if(e>0){this.scheduleLivenessCheck(e);return}let t=this.client.inboundActivitySeq??this.inboundActivityVersion;if(this.lastLivenessFailureActivityVersion!==null&&t!==this.lastLivenessFailureActivityVersion){this.resetLivenessProbeFailures(),this.lastTerminalActivityAtMs=Date.now(),this.scheduleLivenessCheck();return}let n=d;this.livenessProbeInFlight=!0,this.client.request(`terminal.list`,void 0,{timeoutMs:f}).then(()=>{this.resetLivenessProbeFailures(),this.lastTerminalActivityAtMs=Date.now()}).catch(()=>{if(this.streams.size===0){this.resetLivenessProbeFailures();return}let e=this.client.inboundActivitySeq??this.inboundActivityVersion;if(e!==t){this.resetLivenessProbeFailures(),this.lastTerminalActivityAtMs=Date.now();return}if(this.livenessProbeFailures+=1,this.lastLivenessFailureActivityVersion=e,this.livenessProbeFailures>=p){this.forceReconnect(`terminal liveness timeout`);return}n=m}).finally(()=>{this.livenessProbeInFlight=!1,this.scheduleLivenessCheck(n)})}input(e,t){return this.requestAction(`terminal.input`,e,{sessionId:e,data:t})}resize(e,t,n){return this.requestAction(`terminal.resize`,e,{sessionId:e,cols:t,rows:n})}async requestAction(e,t,n){let r=this.streams.get(t);(await this.client.request(e,n).catch(()=>null))?.ok===!1&&r&&this.streams.get(t)===r&&this.deliverExit(t,r,{exitCode:null,signal:null,reason:`disconnected`,error:`Terminal session is no longer available. Open a new terminal session.`})}async close(e){this.removeStream(e),this.pending.delete(e),await this.client.request(`terminal.close`,{sessionId:e}).catch(()=>void 0),this.pending.delete(e),this.maybeUnsubscribe()}get size(){return this.streams.size}dispose(){this.disposed=!0;for(let e of this.streams.values())e.abort.abort();this.streams.clear(),this.pending.clear(),this.stopLiveness(),this.dropSubscriptions()}maybeUnsubscribe(){this.streams.size===0&&this.pendingOpenCount===0&&(this.pending.clear(),this.stopLiveness(),this.dropSubscriptions())}stopLiveness(){this.resetLivenessProbeFailures(),this.livenessTimer&&=(clearTimeout(this.livenessTimer),null)}dropSubscriptions(){this.unsubscribe?.(),this.unsubscribe=null}}})))()}var b=t({prepareCatalogTerminal:()=>S});function x(e){w.delete(e),clearTimeout(e.expiry),e.connection.close(e.result.sessionId),e.connection.dispose()}async function S(e,t,n){if(!n())throw Error(r(`terminal.startCancelled`));let i=new v(e),o=new a(262144,{mode:`drop-oldest`,fit:(e,t)=>e.slice(-t)},e=>e.length),s=null,c=null;try{let a=await i.start(t,{onData:e=>s?s.onData(e):void o.push(e),onReplay:e=>{if(s)return s.onReplay(e);o.drain(),o.push(e.data)},onExit:e=>{c=e,s?.onExit(e)}});if(!n())throw i.close(a.sessionId),Error(r(`terminal.startCancelled`));if(w.size>=8){let e=w.values().next().value;e&&x(e)}let l={client:e,connection:i,result:a,expiry:setTimeout(()=>x(l),6e4),bind:e=>{s=e;for(let t of o.drain())e.onData(t);c&&e.onExit(c)}};return w.add(l),a}catch(e){throw i.dispose(),e}}function C(e,t){let n=[...w].find(n=>n.result.sessionId===e&&n.client===t);return n?(w.delete(n),clearTimeout(n.expiry),n):null}var w;function T(){return(T=e((()=>{o(),y(),n(),w=new Set})))()}export{g as a,a as c,v as i,o as l,T as n,_ as o,C as r,y as s,b as t};