beeos-claw 0.6.66-cloud.4 → 0.6.66-cloud.5
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash,randomUUID}from"node:crypto";import{EventEmitter}from"node:events";import WebSocket from"ws";import{createTerminalAgentAuth,terminalAgentAuthSigningMessage as harnessTerminalAgentAuthSigningMessage,terminalAgentWebSocketUrl}from"@beeos-ai/cloud-harness-sdk";export function terminalAgentAuthSigningMessage(e){return harnessTerminalAgentAuthSigningMessage({publicKey:e.public_key,timestamp:e.timestamp,nonce:e.nonce,runtimeLeaseCredential:e.runtimeLeaseCredential,handlerIdentity:e.handlerIdentity,runtimeEpoch:e.runtimeEpoch,leaseId:e.leaseId})}export function createTerminalLeaseBoundAgentAuth(e){if(!(32===e.keys.publicKey.length&&[32,48].includes(e.keys.privateKey.length)&&e.lease.instanceId&&e.lease.leaseId&&e.lease.handlerIdentity&&e.lease.runtimeLeaseCredential&&isPositiveRuntimeEpoch(e.lease.runtimeEpoch)&&Number.isSafeInteger(e.timestamp)&&!(e.timestamp<0)&&e.nonce))throw new Error("invalid Terminal runtime lease authority binding");return createTerminalAgentAuth({lease:{instanceId:e.lease.instanceId,leaseId:e.lease.leaseId,runtimeEpoch:e.lease.runtimeEpoch,runtimeLeaseCredential:e.lease.runtimeLeaseCredential,handlerIdentity:e.lease.handlerIdentity},keys:e.keys,timestamp:e.timestamp,nonce:e.nonce})}export class TerminalLeaseBoundBridgeClient extends EventEmitter{options;state="idle";socket;unsubscribe;expiryTimer;reconnectTimer;generation=0;stopped=!0;authenticatedBindingHash;authorityEpochBindingHash;transition=Promise.resolve();constructor(e){super(),this.options=e}async connect(){this.unsubscribe||(this.unsubscribe=this.options.authority.subscribeAuthority((e,t)=>this.onAuthorityChanged(e,t))),this.stopped=!1;const e=this.options.authority.authorityLease;if(!e)throw new Error("active runtime registration lease required for Terminal auth");await this.queueTransition(()=>this.replaceConnection(e))}async send(e){const t=this.socket;if("connected"!==this.state||!t||t.readyState!==WebSocket.OPEN)throw new Error("Terminal lease-bound Bridge is not connected");await new Promise((i,n)=>t.send(e,e=>e?n(e):i()))}async close(e=!0){this.stopped=!0,this.clearTimers(),this.unsubscribe?.(),this.unsubscribe=void 0,this.authenticatedBindingHash=void 0,this.authorityEpochBindingHash=void 0,this.generation++,await this.closeSocket(e),this.state="closed"}onAuthorityChanged(e,t){if(this.stopped)return;if(!e)return void this.fenceAuthority(void 0===t);this.scheduleExpiryFence(e);const i=authorityEpochHash(e),n=authorityBindingHash(e);return this.authorityEpochBindingHash&&i!==this.authorityEpochBindingHash?(this.authorityEpochBindingHash=i,this.emit("transportEpochChanged"),void this.queueTransition(()=>this.replaceConnection(e)).catch(e=>this.emitError(e))):n!==this.authenticatedBindingHash?"connected"===this.state&&this.authenticatedBindingHash?(this.authenticatedBindingHash=n,void(this.authorityEpochBindingHash??=i)):void this.queueTransition(()=>this.replaceConnection(e)).catch(e=>this.emitError(e)):void 0}async replaceConnection(e){if(this.stopped||null===this.options.authority.authorityLease)return;this.clearReconnectTimer();const t=++this.generation;if(await this.closeSocket(!1),this.stopped||t!==this.generation)return;this.state="connecting";const i=new WebSocket(terminalAgentWebSocketUrl(this.options.bridgeUrl));this.socket=i;const n=authorityBindingHash(e);await new Promise((s,r)=>{let o=!1;const a=setTimeout(()=>{c(new Error("Terminal auth timeout")),i.readyState!==WebSocket.CLOSED&&i.terminate()},this.options.authTimeoutMs??1e4),h=()=>{clearTimeout(a),i.off("open",u)},c=e=>{h(),o||r(e)},u=()=>{const e=this.options.authority.authorityLease;if(!e||authorityBindingHash(e)!==n||t!==this.generation)return c(new Error("Terminal runtime lease changed during auth")),void i.close();const s=createTerminalLeaseBoundAgentAuth({lease:e,keys:this.options.keys,timestamp:Math.floor((this.options.now??Date.now)()/1e3),nonce:(this.options.nonce??randomUUID)()});i.send(JSON.stringify(s),e=>{e&&c(e)})};i.on("open",u),i.on("message",r=>{if(!o){try{if("auth_ok"!==JSON.parse(r.toString()).type)return}catch{return}return o=!0,h(),t!==this.generation?void i.close():(this.authenticatedBindingHash=n,this.authorityEpochBindingHash=authorityEpochHash(e),this.state="connected",this.scheduleExpiryFence(e),this.emit("connected",{handlerIdentity:e.handlerIdentity}),void s())}this.emit("message",r)}),i.on("error",e=>{this.emitError(e),c(e)}),i.on("close",(e,i)=>{h(),o||r(new Error(`Terminal auth rejected: ${i.toString()||"connection closed"}`)),t===this.generation&&(this.socket=void 0,this.authenticatedBindingHash=void 0,this.state="idle",this.emit("disconnected",i.toString()||"connection closed"),1008!==e?!this.stopped&&this.options.authority.authorityLease&&this.scheduleReconnect():this.fenceAuthority(!
|
|
1
|
+
import{createHash,randomUUID}from"node:crypto";import{EventEmitter}from"node:events";import WebSocket from"ws";import{createTerminalAgentAuth,terminalAgentAuthSigningMessage as harnessTerminalAgentAuthSigningMessage,terminalAgentWebSocketUrl}from"@beeos-ai/cloud-harness-sdk";export function terminalAgentAuthSigningMessage(e){return harnessTerminalAgentAuthSigningMessage({publicKey:e.public_key,timestamp:e.timestamp,nonce:e.nonce,runtimeLeaseCredential:e.runtimeLeaseCredential,handlerIdentity:e.handlerIdentity,runtimeEpoch:e.runtimeEpoch,leaseId:e.leaseId})}export function createTerminalLeaseBoundAgentAuth(e){if(!(32===e.keys.publicKey.length&&[32,48].includes(e.keys.privateKey.length)&&e.lease.instanceId&&e.lease.leaseId&&e.lease.handlerIdentity&&e.lease.runtimeLeaseCredential&&isPositiveRuntimeEpoch(e.lease.runtimeEpoch)&&Number.isSafeInteger(e.timestamp)&&!(e.timestamp<0)&&e.nonce))throw new Error("invalid Terminal runtime lease authority binding");return createTerminalAgentAuth({lease:{instanceId:e.lease.instanceId,leaseId:e.lease.leaseId,runtimeEpoch:e.lease.runtimeEpoch,runtimeLeaseCredential:e.lease.runtimeLeaseCredential,handlerIdentity:e.lease.handlerIdentity},keys:e.keys,timestamp:e.timestamp,nonce:e.nonce})}export class TerminalLeaseBoundBridgeClient extends EventEmitter{options;state="idle";socket;unsubscribe;expiryTimer;reconnectTimer;generation=0;stopped=!0;authenticatedBindingHash;authorityEpochBindingHash;transition=Promise.resolve();constructor(e){super(),this.options=e}async connect(){this.unsubscribe||(this.unsubscribe=this.options.authority.subscribeAuthority((e,t)=>this.onAuthorityChanged(e,t))),this.stopped=!1;const e=this.options.authority.authorityLease;if(!e)throw new Error("active runtime registration lease required for Terminal auth");await this.queueTransition(()=>this.replaceConnection(e))}async send(e){const t=this.socket;if("connected"!==this.state||!t||t.readyState!==WebSocket.OPEN)throw new Error("Terminal lease-bound Bridge is not connected");await new Promise((i,n)=>t.send(e,e=>e?n(e):i()))}async close(e=!0){this.stopped=!0,this.clearTimers(),this.unsubscribe?.(),this.unsubscribe=void 0,this.authenticatedBindingHash=void 0,this.authorityEpochBindingHash=void 0,this.generation++,await this.closeSocket(e),this.state="closed"}onAuthorityChanged(e,t){if(this.stopped)return;if(!e)return void this.fenceAuthority(void 0===t);this.scheduleExpiryFence(e);const i=authorityEpochHash(e),n=authorityBindingHash(e);return this.authorityEpochBindingHash&&i!==this.authorityEpochBindingHash?(this.authorityEpochBindingHash=i,this.emit("transportEpochChanged"),void this.queueTransition(()=>this.replaceConnection(e)).catch(e=>this.emitError(e))):n!==this.authenticatedBindingHash?"connected"===this.state&&this.authenticatedBindingHash?(this.authenticatedBindingHash=n,void(this.authorityEpochBindingHash??=i)):void this.queueTransition(()=>this.replaceConnection(e)).catch(e=>this.emitError(e)):void 0}async replaceConnection(e){if(this.stopped||null===this.options.authority.authorityLease)return;this.clearReconnectTimer();const t=++this.generation;if(await this.closeSocket(!1),this.stopped||t!==this.generation)return;this.state="connecting";const i=new WebSocket(terminalAgentWebSocketUrl(this.options.bridgeUrl));this.socket=i;const n=authorityBindingHash(e);await new Promise((s,r)=>{let o=!1;const a=setTimeout(()=>{c(new Error("Terminal auth timeout")),i.readyState!==WebSocket.CLOSED&&i.terminate()},this.options.authTimeoutMs??1e4),h=()=>{clearTimeout(a),i.off("open",u)},c=e=>{h(),o||r(e)},u=()=>{const e=this.options.authority.authorityLease;if(!e||authorityBindingHash(e)!==n||t!==this.generation)return c(new Error("Terminal runtime lease changed during auth")),void i.close();const s=createTerminalLeaseBoundAgentAuth({lease:e,keys:this.options.keys,timestamp:Math.floor((this.options.now??Date.now)()/1e3),nonce:(this.options.nonce??randomUUID)()});i.send(JSON.stringify(s),e=>{e&&c(e)})};i.on("open",u),i.on("message",r=>{if(!o){try{if("auth_ok"!==JSON.parse(r.toString()).type)return}catch{return}return o=!0,h(),t!==this.generation?void i.close():(this.authenticatedBindingHash=n,this.authorityEpochBindingHash=authorityEpochHash(e),this.state="connected",this.scheduleExpiryFence(e),this.emit("connected",{handlerIdentity:e.handlerIdentity}),void s())}this.emit("message",r)}),i.on("error",e=>{this.emitError(e),c(e)}),i.on("close",(e,i)=>{h(),o||r(new Error(`Terminal auth rejected: ${i.toString()||"connection closed"}`)),t===this.generation&&(this.socket=void 0,this.authenticatedBindingHash=void 0,this.state="idle",this.emit("disconnected",i.toString()||"connection closed"),1008!==e?!this.stopped&&this.options.authority.authorityLease&&this.scheduleReconnect():this.fenceAuthority(!o))})})}fenceAuthority(e){this.clearTimers(),this.authenticatedBindingHash=void 0,this.authorityEpochBindingHash=void 0,this.generation++;const t=this.socket;this.socket=void 0,this.state="idle",t&&t.readyState!==WebSocket.CLOSED&&t.terminate(),this.emit("authorityLost",{recoverable:e})}scheduleExpiryFence(e){this.expiryTimer&&clearTimeout(this.expiryTimer);const t=authorityBindingHash(e);this.expiryTimer=setTimeout(()=>{const e=this.options.authority.authorityLease;e?authorityBindingHash(e)===t&&(Date.parse(e.leaseExpiresAt)>(this.options.now??Date.now)()?this.scheduleExpiryFence(e):this.fenceAuthority(!0)):this.fenceAuthority(!0)},Math.min(2147483647,Math.max(0,Date.parse(e.leaseExpiresAt)-(this.options.now??Date.now)()))),this.expiryTimer.unref?.()}scheduleReconnect(){this.reconnectTimer||this.stopped||(this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=void 0;const e=this.options.authority.authorityLease;e&&this.queueTransition(()=>this.replaceConnection(e)).catch(e=>{this.emitError(e),this.scheduleReconnect()})},this.options.reconnectDelayMs??1e3),this.reconnectTimer.unref?.())}async closeSocket(e){const t=this.socket;this.socket=void 0,t&&t.readyState!==WebSocket.CLOSED&&(e&&t.readyState===WebSocket.OPEN?await new Promise(e=>{t.once("close",()=>e()),t.close()}):t.terminate())}queueTransition(e){const t=this.transition.then(e,e);return this.transition=t.catch(()=>{}),t}clearReconnectTimer(){this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0}clearTimers(){this.clearReconnectTimer(),this.expiryTimer&&clearTimeout(this.expiryTimer),this.expiryTimer=void 0}emitError(e){this.listenerCount("error")>0&&this.emit("error",e instanceof Error?e:new Error(String(e)))}}function authorityEpochHash(e){return createHash("sha256").update(`${e.instanceId}\0${e.leaseId}\0${e.handlerIdentity}\0${e.runtimeEpoch}`).digest("hex")}function authorityBindingHash(e){return createHash("sha256").update(`${e.instanceId}\0${e.leaseId}\0${e.handlerIdentity}\0${e.runtimeEpoch}\0${e.runtimeLeaseCredential}\0${e.leaseExpiresAt}`).digest("hex")}function isPositiveRuntimeEpoch(e){return"string"==typeof e&&/^[1-9][0-9]*$/.test(e)&&BigInt(e)<=18446744073709551615n}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "beeos-claw",
|
|
3
|
-
"version": "0.6.66-cloud.
|
|
3
|
+
"version": "0.6.66-cloud.5",
|
|
4
4
|
"description": "OpenClaw plugin that bridges the BeeOS platform with the local OpenClaw Gateway, providing file transfer, ACP bridge, and observability.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "BeeOS <dev@beeos.ai>",
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
"fast-uri": ">=3.1.4",
|
|
89
89
|
"brace-expansion": ">=5.0.9"
|
|
90
90
|
},
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "2e2d94b544e224a005f81c54bf4ef728a730060c"
|
|
92
92
|
}
|