beeos-claw 0.6.96 → 0.6.97

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 CHANGED
@@ -551,3 +551,20 @@ Pre-release versions never match semver ranges like `^0.2.40`, so production con
551
551
  ## License
552
552
 
553
553
  MIT
554
+
555
+ ### Host model configuration
556
+
557
+ The plugin reads OpenClaw's live `runtime.config.current()` snapshot. Registration
558
+ uses the host `api.config` if no runtime API is available; plugin options are never
559
+ used as model configuration. Session model references use configured provider ids
560
+ (including BeeWork `bw_...` and explicitly configured `arouter`) without an implicit
561
+ provider fallback. Each model operation re-reads the config to observe reloads.
562
+ Omitting a task model keeps OpenClaw's bound-agent default and validation authority.
563
+
564
+ A model preparation failure before runtime dispatch writes the existing
565
+ `runtime_error` part with `code: model_preparation_failed`, then fails the reply.
566
+ This code means this turn was not dispatched to the model runtime; it does not
567
+ assert that a failed session-model patch left session metadata unchanged. It does
568
+ not authorize automatic retries. Failures after dispatch and uncertain terminal
569
+ delivery retain their existing semantics. Cloud's existing UHP projection forwards
570
+ the code; BeeWork maps the confirmed failed terminal to a startup failure.
@@ -1 +1 @@
1
- import{createHash,randomUUID}from"node:crypto";import{dispatchRuntimeReplyWithRoute,hasRuntimeReplyApi}from"./runtime/reply-router.js";import{createImReplySink}from"./runtime/im-reply-sink.js";import{SerializedCallbackQueue}from"./runtime/callback-queue.js";import{promptRunKey}from"./runtime/prompt-run-store.js";import{classifyAgentRuntimeFailure}from"./runtime/agent-runtime-failure-classifier.js";import{SESSION_RECOVERY_REQUIRED_CODE,SESSION_RECOVERY_REQUIRED_MESSAGE}from"./runtime/session-mutation-coordinator.js";import{interceptAgentRuntimeFailures,messageStopReasonForRuntimeFailure,SESSION_BUSY_PUBLIC_MESSAGE}from"./runtime/im-runtime-failure-policy.js";import{writeRuntimeFailure}from"./runtime/write-runtime-failure.js";import{maybeRenameImConversationTitle}from"./runtime/conversation-title.js";import{settleBeforeTerminal}from"./approval/bridge.js";import{logChatLatency}from"./chat-latency.js";const normalizePositiveTimeoutMs=e=>{if("number"!=typeof e||!Number.isFinite(e))return;const n=Math.max(0,Math.trunc(e));return n>0?n:void 0},ABORT_TERMINAL_GRACE_MS=1e4,PRE_RUN_LOOP_PROBE_MS=100,PRE_RUN_LOOP_LAG_LOG_MS=500,formatErrMessage=e=>{if(e instanceof Error)return e.message;if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}},failMessageStream=async(e,n)=>{void 0!==n.body&&e.setBody(n.body),await e.fail(void 0===n.stopReason?void 0:{stopReason:n.stopReason})};export const deterministicReplyMessageId=(e,n,t,r)=>`${e}_${createHash("sha256").update(`${n}:${t}:${r}`).digest("hex").slice(0,32)}`;export const dispatchImInboundPrompt=async e=>{const{runtime:n,prompt:t,client:r,logger:a,promptRunStore:i,assistantMessageCommitRouter:o,toolResultObservationRouter:s,modelCallObservationRouter:c,sessionMutationCoordinator:l,abortTransport:d,activeRunAuthority:u}=e;if(!hasRuntimeReplyApi(n))return a.warn?.(`[im] runtime dispatch skipped reason=reply_api_unavailable channel=${t.channelId} in_reply_to=${t.inboundMessageId}`),e.onLifecycleEvent?.({type:"skipped",reason:"reply_api_unavailable",channelId:t.channelId,inboundMessageId:t.inboundMessageId}),!1;const m=t.requestId??t.inboundMessageId,p=e.runtimeRunId??randomUUID();if(!p)throw new Error("runtime run id required");const I=Date.now();logChatLatency(a,"claw.inbound.received",m,I,{origin:e.origin??"im",request_id_source:t.requestId?"realtime_correlation":"message_id_fallback"});const g=e.origin??"im",h={protocol:"im",requestId:m,sessionId:t.sessionKey??"agent:main",sourceMessageId:t.inboundMessageId,chatId:t.channelId,origin:g},y=async(n,r)=>{if(e.onTerminalResult)try{await e.onTerminalResult(n,r)}catch(e){a.warn?.(`[im] terminal business callback failed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}},_=promptRunKey(t.channelId,t.inboundMessageId),R=t.sessionKey??"agent:main",f=new AbortController;let v,w,b,E,M,S,$,C;const q=new Promise((e,n)=>{C=n});e.onNativeRunCompletion&&q.catch(()=>{});const N=e.onNativeRunCompletion?{chatAbort:(e,n)=>(b=Promise.resolve().then(()=>d.chatAbort(e,n)),b)}:d;let k;const O=()=>{void 0!==k&&(clearTimeout(k),k=void 0)},T=async e=>{if($??=e,f.abort(e),!v)return{ok:!0};const n=await l.requestCancel(v,N);return n.ok?n.terminalObservation.then(e=>{e.ok||C(new Error(SESSION_RECOVERY_REQUIRED_CODE))}):C(new Error(SESSION_RECOVERY_REQUIRED_CODE)),{ok:n.ok}};if(e.waitIfExclusive)try{await e.waitIfExclusive("im_dispatch",f.signal)}catch(n){return a.warn?.(`[im] runtime dispatch aborted waiting for exclusive mutation requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:n instanceof Error?n.message:String(n),cause:"abort"}),!1}if(!i.register(_,{requestId:m,channelId:t.channelId,requestCancel:T,startedAt:I,sessionKey:R}))return a.warn?.(`[im] runtime dispatch rejected duplicate inboundMessageId=${t.inboundMessageId} requestId=${m} channel=${t.channelId}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:"duplicate_inbound_message_id",cause:"abort"}),!1;const L=e.retainedStream?.id??deterministicReplyMessageId("asst",t.channelId,t.inboundMessageId,t.selfPrincipalId),A={conversationId:t.channelId,clientMessageId:L,idempotencyKey:L,replyTo:e.inReplyTo??t.inboundMessageId,requestId:m,type:"agent_reply",content:{}};let D=()=>{};const F=settleBeforeTerminal(e.retainedStream??r.messages.startStream(A),()=>D());let U,K=!1;try{const e=await F.opened();K="duplicate"===e.outcome,logChatLatency(a,"claw.reply_stream.opened",m,I,{outcome:e.outcome})}catch(n){let o="unconfirmed";try{o=(await r.messages.getEnvelope(t.channelId,L)).state}catch{}return a.warn?.(`[im] runtime reply stream open outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} reply_id=${L} reconciled_state=${o}: ${formatErrMessage(n)}; runtime_not_invoked`),e.onLifecycleEvent?.({type:"skipped",reason:"reply_open_outcome_unknown",channelId:t.channelId,inboundMessageId:t.inboundMessageId}),i.unregister(_),!1}if(K)return a.info?.(`[im] runtime dispatch skipped existing deterministic reply requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}`),e.onLifecycleEvent?.({type:"skipped",reason:"idempotent_reply_exists",channelId:t.channelId,inboundMessageId:t.inboundMessageId}),i.unregister(_),!1;const P=()=>{T(e.abortSignal?.reason).catch(e=>{C(e instanceof Error?e:new Error(String(e)))})};e.abortSignal?.addEventListener("abort",P,{once:!0}),e.abortSignal?.aborted&&P();const Q=new SerializedCallbackQueue,j=createImReplySink({stream:F,persistObservedToolResults:void 0!==e.retainedStream,htmlDelivery:e.htmlDelivery,abortSignal:f.signal,callbackQueue:Q,...e.onNativeRunCompletion?{onCallbackFailure:e=>Q.fail(e)}:{},logger:a,requestId:m,startedAtMs:I,runId:p,channelId:t.channelId,inboundMessageId:t.inboundMessageId,origin:g,sessionKey:R,onAgentRunStart:n=>{l.bindRun(v,n),e.onNativeAgentRunStart?.(n),void 0!==U&&logChatLatency(a,"claw.runtime.pre_run_completed",m,U)}}),G=interceptAgentRuntimeFailures(j,"im_runtime",e=>a.warn?.(`[im] runtime failure reply suppressed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} error_code=${e.errorCode}`)),Y=G.sink;let x=!1,B=!1;const V=async n=>{e.onNativeRunCompletion||Y.dispatcher.markComplete(n);try{e.onNativeRunCompletion&&Y.dispatcher.markComplete(n),await Y.dispatcher.waitForIdle()}catch(n){if(e.onNativeRunCompletion)throw Q.fail(n),n}},z=()=>{if(e.onNativeRunCompletion)return;O();const n=normalizePositiveTimeoutMs(e.abortTerminalGraceMs)??1e4;k=setTimeout(()=>{k=void 0,(async()=>{if(F.isTerminated)return;const e=f.signal.reason??$,n="string"==typeof e&&e.startsWith("chat_cancel");if(await V("failure"),!F.isTerminated)try{n?await F.cancel({stopReason:"user_stop"}):await failMessageStream(F,{body:SESSION_RECOVERY_REQUIRED_MESSAGE,stopReason:"error"}),a.warn?.(`[im] abort settlement watchdog terminalized reply requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} user_cancel=${n}`)}catch(e){a.warn?.(`[im] abort settlement watchdog terminal write failed requestId=${m} channel=${t.channelId}: ${formatErrMessage(e)}`)}})()},n)};f.signal.aborted?z():f.signal.addEventListener("abort",z,{once:!0});const W=()=>{if(!f.signal.aborted)return;const e=f.signal.reason;throw e instanceof Error?e:new Error(String(e??"runtime dispatch aborted"))};let J,H,X,Z,ee,ne,te,re,ae;const ie=async e=>{if(!v)throw new Error("session_mutation_not_acquired");const n=await l.converge(v,e);return n.ok?(J=n.permit,!0):(a.error?.(`[im] session mutation recovery required requestId=${m} sessionKey=${R} reason=${n.recovery.reason}`),H={code:n.recovery.code,reason:n.recovery.reason,sessionKey:n.recovery.sessionKey,operationId:n.recovery.operationId,surface:"message_service",...n.recovery.terminalKind?{terminalKind:n.recovery.terminalKind}:{}},!1)};let oe=!0;const se=async(e,n)=>{for(let r=0;;r+=1)try{return await n(),void(oe=!1)}catch(n){if(r>=1)return oe=!0,void a.warn?.(`[im] ${e} failed after terminal redelivery requestId=${m} channel=${t.channelId}: ${formatErrMessage(n)}`);a.warn?.(`[im] ${e} failed; redelivering terminal once requestId=${m} channel=${t.channelId}: ${formatErrMessage(n)}`)}};try{if(W(),e.onNativeRunCompletion&&!e.nativeActiveRunRegistration)throw new Error("native MS Start registration required");const d=l.tryStartInteractive({sessionKey:R,label:"im_chat_message"},"message_service");if(!d.ok){try{await failMessageStream(F,{body:SESSION_BUSY_PUBLIC_MESSAGE,stopReason:"error"})}catch(e){a.warn?.(`[im] session busy terminal write failed channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}return a.warn?.(`[im] session write gate busy sessionKey=${R} channel=${t.channelId} in_reply_to=${t.inboundMessageId} active_operation=${d.activeOperationId??"unknown"}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:"session_busy",cause:"runtime_error"}),!1}if(v=d.token,logChatLatency(a,"claw.session_gate.acquired",m,I),l.bindRun(v,p),Z=o.register(R,j),ee=s.register(R,j),ne=e.approvalStreams?.bindSession(R,j.approvalParts),te=e.questionStreams?.bindSession(R,j.questionParts,{conversationId:t.channelId,replyMessageId:F.id}),D=()=>{ne?.(),te?.()},re=c.register(p,{requestId:m,startedAtMs:I,logger:a}),u){const n=l.snapshot(R);X=e.onNativeRunCompletion?{...e.nativeActiveRunRegistration}:{runtimeConversationUid:t.channelId,runtimeSessionKey:t.channelId,historyGeneration:u.historyGeneration(t.channelId),targetMessageId:t.inboundMessageId,runtimeRunId:p,activeRunRegistrationId:`im:${n?.operationId??p}`},u.activeRuns.register(X,async()=>{const e=`chat_cancel:activeRun:${X.activeRunRegistrationId}`,n=await i.abort(_,e);return n.ok||"already_aborted"===n.reason?"accepted":"terminal_committing"===n.reason||"not_found"===n.reason?"already_terminal":"recovery_required"})}W(),a.info?.(`[im] runtime dispatching requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} origin=${g}`),e.onLifecycleEvent?.({type:"dispatch_start",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId}),e.onNativeRunCompletion&&e.assertNativeTarget&&(await e.assertNativeTarget(),W()),e.onNativeRunCompletion&&e.prepareNativeModel&&(await e.prepareNativeModel(v),W(),await(e.assertNativeTarget?.()),W());const f=t.modelOverrideId;"string"==typeof f&&f.length>0&&R.length>0&&e.applyTurnModel&&(await e.applyTurnModel(R,f),B=!0,W()),U=Date.now(),ae=e.enterTurn?.(R,p),logChatLatency(a,"claw.runtime.invoke",m,I);const S=setTimeout(()=>{const e=Date.now()-U-100;e>=500&&logChatLatency(a,"claw.runtime.event_loop_lag",m,U,{lag_ms:e,phase:"pre_run"})},100);S.unref?.();const $=()=>dispatchRuntimeReplyWithRoute({runtime:n,pluginConfig:e.pluginConfig,preparedPrompt:t.dispatchInput,replyRoute:h,replySinks:{im:Y},onDispatchInvoked:n=>{if(x=!0,e.onNativeRunCompletion){w=n;const t=new Promise((e,n)=>{E=e,M=n});t.catch(()=>{}),e.onNativeRunCompletion({runtimeRunId:p,token:v,hostCompletion:n,completion:t})}logChatLatency(a,"claw.runtime.dispatch_returned",m,U)}}),C=ae?ae.run($):$(),N=e.onNativeRunCompletion?await C:await Promise.race([C,q]).finally(()=>{});e.onNativeRunCompletion&&(await w,await b);const k=G.detectedFailure();if(k)throw new Error(k.diagnosticMessage);if(W(),await V("success"),e.onNativeRunCompletion&&await b,W(),void 0===Y.dispatcher.getTerminalErrorText?.()&&e.htmlDelivery?.assertComplete(),!i.claimTerminal(_,"completion")){if(W(),"cancelling"===i.phase(_))throw new Error("cancellation in progress");throw new Error("terminal outcome already claimed")}if(!await ie("completed"))return await failMessageStream(F,{body:SESSION_RECOVERY_REQUIRED_MESSAGE,stopReason:"error"}).catch(()=>{}),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:SESSION_RECOVERY_REQUIRED_CODE,cause:"runtime_error",...H?{recovery:H}:{}}),!1;const O=Y.dispatcher.getTerminalErrorText?.();if(void 0!==O){let n=!1;const r=classifyAgentRuntimeFailure({raw:O,source:"im_runtime",runtimeKind:"openclaw"});try{await writeRuntimeFailure(F,{body:r.publicMessage,stopReason:messageStopReasonForRuntimeFailure(r),businessErrorCode:r.businessErrorCode})}catch(e){n=!0,a.warn?.(`[im] runtime reply stream error-terminal write outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}return u&&X&&u.activeRuns.markTerminal(X,"failed"),a.warn?.(`[im] runtime dispatch ended with an error terminal requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} counts=${JSON.stringify(N.counts)} terminalWriteFailed=${n} elapsed_ms=${Date.now()-I}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:"runtime_error_terminal_reply",cause:"runtime_error"}),n||await y("",O),!1}let T=!1;try{await F.finalize({stopReason:"end_turn"})}catch(e){T=!0,a.warn?.(`[im] runtime reply stream finalize outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}u&&X&&u.activeRuns.markTerminal(X,"completed");const L={...N.counts,source:j.getSourceCount()};a.info?.(`[im] runtime dispatch completed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} counts=${JSON.stringify(L)} elapsed_ms=${Date.now()-I}`),logChatLatency(a,"claw.turn.terminal",m,I,{outcome:T?"outcome_unknown":"completed",tool_count:L.tool}),e.onLifecycleEvent?.({type:"dispatch_complete",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,counts:L,...T?{terminalWriteFailed:!0}:{}});const A=Y.dispatcher.getAccumulatedBody?.()??"";T||await y(A,"");const K="string"==typeof t.dispatchInput.message?t.dispatchInput.message:"";return maybeRenameImConversationTitle({client:r,conversationId:t.channelId,question:K,answer:A,logger:a}),!0}catch(n){S=n,e.onNativeRunCompletion&&(await(w?.then(()=>{},()=>{})),await b),await V("failure"),e.onNativeRunCompletion&&await b;const r=f.signal.aborted,o=r?f.signal.reason:void 0,s="cancelling"===i.phase(_),c=o??$,l="string"==typeof c&&c.startsWith("chat_cancel");let d="runtime_error";(r||s)&&(d="abort");const p=s||l||r?"cancellation":"completion";if(!i.claimTerminal(_,p))throw a.warn?.(`[im] terminal claim raced requestId=${m} channel=${t.channelId}; best-effort envelope terminal if still streaming`),F.isTerminated?oe=!1:await se("raced terminal write",()=>l?F.cancel({stopReason:"user_stop"}):failMessageStream(F,{body:formatErrMessage(n),stopReason:"error"})),n;const g=l?"cancelled":"error";if(u&&X&&!e.onNativeRunCompletion&&u.activeRuns.markTerminal(X,"cancelled"===g?"cancelled":"failed"),v&&!await ie(g))throw u&&X&&e.onNativeRunCompletion&&u.activeRuns.markTerminal(X,"cancelled"===g?"cancelled":"failed"),l?await se("session recovery cancel",()=>F.cancel({stopReason:"user_stop"})):await se("session recovery terminal write",()=>failMessageStream(F,{body:SESSION_RECOVERY_REQUIRED_MESSAGE,stopReason:"error"})),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:SESSION_RECOVERY_REQUIRED_CODE,cause:d,...H?{recovery:H}:{}}),n;u&&X&&e.onNativeRunCompletion&&u.activeRuns.markTerminal(X,"cancelled"===g?"cancelled":"failed");const h=classifyAgentRuntimeFailure({raw:n,source:"im_runtime",runtimeKind:"openclaw",requestAborted:l}),R=l?h:G.detectedFailure()??h;throw l?await se("runtime stream cancel",()=>F.cancel({stopReason:"user_stop"})):await se("runtime stream terminal write",()=>writeRuntimeFailure(F,{body:R.publicMessage,stopReason:messageStopReasonForRuntimeFailure(R),businessErrorCode:R.businessErrorCode})),a.warn?.(`[im] runtime dispatch failed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} cause=${d} dispatchInvoked=${x} error_code=${R.errorCode}`),logChatLatency(a,"claw.turn.terminal",m,I,{outcome:d,error_code:R.errorCode}),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:R.errorCode,cause:d}),l||oe||await y("",R.publicMessage),n}finally{if(e.onNativeRunCompletion&&(J?E?.(J):(x&&v&&oe&&l.requireRecovery(v,"terminal_not_observed"),M?.(S??new Error(SESSION_RECOVERY_REQUIRED_CODE)))),e.abortSignal?.removeEventListener("abort",P),x&&!J||ae?.close(),O(),re?.(),ee?.(),ne?.(),te?.(),Z?.(),i.unregister(_),B&&e.restoreTurnModel&&R)try{await e.restoreTurnModel(R)}catch(e){a.error?.(`[im] turn model restore failed requestId=${m} sessionKey=${R}: ${formatErrMessage(e)}`)}x?J&&l.release(J):l.releaseBeforeRuntime(v)}};
1
+ import{ModelPreparationError,MODEL_PREPARATION_FAILED,MODEL_PREPARATION_MESSAGE}from"./runtime/openclaw-config.js";import{createHash,randomUUID}from"node:crypto";import{dispatchRuntimeReplyWithRoute,hasRuntimeReplyApi}from"./runtime/reply-router.js";import{createImReplySink}from"./runtime/im-reply-sink.js";import{SerializedCallbackQueue}from"./runtime/callback-queue.js";import{promptRunKey}from"./runtime/prompt-run-store.js";import{classifyAgentRuntimeFailure}from"./runtime/agent-runtime-failure-classifier.js";import{SESSION_RECOVERY_REQUIRED_CODE,SESSION_RECOVERY_REQUIRED_MESSAGE}from"./runtime/session-mutation-coordinator.js";import{interceptAgentRuntimeFailures,messageStopReasonForRuntimeFailure,SESSION_BUSY_PUBLIC_MESSAGE}from"./runtime/im-runtime-failure-policy.js";import{writeRuntimeFailure}from"./runtime/write-runtime-failure.js";import{maybeRenameImConversationTitle}from"./runtime/conversation-title.js";import{settleBeforeTerminal}from"./approval/bridge.js";import{logChatLatency}from"./chat-latency.js";const normalizePositiveTimeoutMs=e=>{if("number"!=typeof e||!Number.isFinite(e))return;const n=Math.max(0,Math.trunc(e));return n>0?n:void 0},ABORT_TERMINAL_GRACE_MS=1e4,PRE_RUN_LOOP_PROBE_MS=100,PRE_RUN_LOOP_LAG_LOG_MS=500,formatErrMessage=e=>{if(e instanceof Error)return e.message;if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}},failMessageStream=async(e,n)=>{void 0!==n.body&&e.setBody(n.body),await e.fail(void 0===n.stopReason?void 0:{stopReason:n.stopReason})};export const deterministicReplyMessageId=(e,n,t,r)=>`${e}_${createHash("sha256").update(`${n}:${t}:${r}`).digest("hex").slice(0,32)}`;export const dispatchImInboundPrompt=async e=>{const{runtime:n,prompt:t,client:r,logger:a,promptRunStore:i,assistantMessageCommitRouter:o,toolResultObservationRouter:s,modelCallObservationRouter:c,sessionMutationCoordinator:l,abortTransport:d,activeRunAuthority:u}=e;if(!hasRuntimeReplyApi(n))return a.warn?.(`[im] runtime dispatch skipped reason=reply_api_unavailable channel=${t.channelId} in_reply_to=${t.inboundMessageId}`),e.onLifecycleEvent?.({type:"skipped",reason:"reply_api_unavailable",channelId:t.channelId,inboundMessageId:t.inboundMessageId}),!1;const m=t.requestId??t.inboundMessageId,p=e.runtimeRunId??randomUUID();if(!p)throw new Error("runtime run id required");const I=Date.now();logChatLatency(a,"claw.inbound.received",m,I,{origin:e.origin??"im",request_id_source:t.requestId?"realtime_correlation":"message_id_fallback"});const g=e.origin??"im",h={protocol:"im",requestId:m,sessionId:t.sessionKey??"agent:main",sourceMessageId:t.inboundMessageId,chatId:t.channelId,origin:g},y=async(n,r)=>{if(e.onTerminalResult)try{await e.onTerminalResult(n,r)}catch(e){a.warn?.(`[im] terminal business callback failed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}},_=promptRunKey(t.channelId,t.inboundMessageId),R=t.sessionKey??"agent:main",E=new AbortController;let f,v,w,b,M,S,$,C;const O=new Promise((e,n)=>{C=n});e.onNativeRunCompletion&&O.catch(()=>{});const N=e.onNativeRunCompletion?{chatAbort:(e,n)=>(w=Promise.resolve().then(()=>d.chatAbort(e,n)),w)}:d;let q;const A=()=>{void 0!==q&&(clearTimeout(q),q=void 0)},T=async e=>{if($??=e,E.abort(e),!f)return{ok:!0};const n=await l.requestCancel(f,N);return n.ok?n.terminalObservation.then(e=>{e.ok||C(new Error(SESSION_RECOVERY_REQUIRED_CODE))}):C(new Error(SESSION_RECOVERY_REQUIRED_CODE)),{ok:n.ok}};if(e.waitIfExclusive)try{await e.waitIfExclusive("im_dispatch",E.signal)}catch(n){return a.warn?.(`[im] runtime dispatch aborted waiting for exclusive mutation requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:n instanceof Error?n.message:String(n),cause:"abort"}),!1}if(!i.register(_,{requestId:m,channelId:t.channelId,requestCancel:T,startedAt:I,sessionKey:R}))return a.warn?.(`[im] runtime dispatch rejected duplicate inboundMessageId=${t.inboundMessageId} requestId=${m} channel=${t.channelId}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:"duplicate_inbound_message_id",cause:"abort"}),!1;const k=e.retainedStream?.id??deterministicReplyMessageId("asst",t.channelId,t.inboundMessageId,t.selfPrincipalId),L={conversationId:t.channelId,clientMessageId:k,idempotencyKey:k,replyTo:e.inReplyTo??t.inboundMessageId,requestId:m,type:"agent_reply",content:{}};let D=()=>{};const P=settleBeforeTerminal(e.retainedStream??r.messages.startStream(L),()=>D());let F,U=!1;try{const e=await P.opened();U="duplicate"===e.outcome,logChatLatency(a,"claw.reply_stream.opened",m,I,{outcome:e.outcome})}catch(n){let o="unconfirmed";try{o=(await r.messages.getEnvelope(t.channelId,k)).state}catch{}return a.warn?.(`[im] runtime reply stream open outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} reply_id=${k} reconciled_state=${o}: ${formatErrMessage(n)}; runtime_not_invoked`),e.onLifecycleEvent?.({type:"skipped",reason:"reply_open_outcome_unknown",channelId:t.channelId,inboundMessageId:t.inboundMessageId}),i.unregister(_),!1}if(U)return a.info?.(`[im] runtime dispatch skipped existing deterministic reply requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}`),e.onLifecycleEvent?.({type:"skipped",reason:"idempotent_reply_exists",channelId:t.channelId,inboundMessageId:t.inboundMessageId}),i.unregister(_),!1;const K=()=>{T(e.abortSignal?.reason).catch(e=>{C(e instanceof Error?e:new Error(String(e)))})};e.abortSignal?.addEventListener("abort",K,{once:!0}),e.abortSignal?.aborted&&K();const G=new SerializedCallbackQueue,j=createImReplySink({stream:P,persistObservedToolResults:void 0!==e.retainedStream,htmlDelivery:e.htmlDelivery,abortSignal:E.signal,callbackQueue:G,...e.onNativeRunCompletion?{onCallbackFailure:e=>G.fail(e)}:{},logger:a,requestId:m,startedAtMs:I,runId:p,channelId:t.channelId,inboundMessageId:t.inboundMessageId,origin:g,sessionKey:R,onAgentRunStart:n=>{l.bindRun(f,n),e.onNativeAgentRunStart?.(n),void 0!==F&&logChatLatency(a,"claw.runtime.pre_run_completed",m,F)}}),Q=interceptAgentRuntimeFailures(j,"im_runtime",e=>a.warn?.(`[im] runtime failure reply suppressed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} error_code=${e.errorCode}`)),Y=Q.sink;let x=!1,B=!1;const V=async n=>{e.onNativeRunCompletion||Y.dispatcher.markComplete(n);try{e.onNativeRunCompletion&&Y.dispatcher.markComplete(n),await Y.dispatcher.waitForIdle()}catch(n){if(e.onNativeRunCompletion)throw G.fail(n),n}},z=()=>{if(e.onNativeRunCompletion)return;A();const n=normalizePositiveTimeoutMs(e.abortTerminalGraceMs)??1e4;q=setTimeout(()=>{q=void 0,(async()=>{if(P.isTerminated)return;const e=E.signal.reason??$,n="string"==typeof e&&e.startsWith("chat_cancel");if(await V("failure"),!P.isTerminated)try{n?await P.cancel({stopReason:"user_stop"}):await failMessageStream(P,{body:SESSION_RECOVERY_REQUIRED_MESSAGE,stopReason:"error"}),a.warn?.(`[im] abort settlement watchdog terminalized reply requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} user_cancel=${n}`)}catch(e){a.warn?.(`[im] abort settlement watchdog terminal write failed requestId=${m} channel=${t.channelId}: ${formatErrMessage(e)}`)}})()},n)};E.signal.aborted?z():E.signal.addEventListener("abort",z,{once:!0});const W=()=>{if(!E.signal.aborted)return;const e=E.signal.reason;throw e instanceof Error?e:new Error(String(e??"runtime dispatch aborted"))};let J,H,X,Z,ee,ne,te,re,ae;const ie=async e=>{if(!f)throw new Error("session_mutation_not_acquired");const n=await l.converge(f,e);return n.ok?(J=n.permit,!0):(a.error?.(`[im] session mutation recovery required requestId=${m} sessionKey=${R} reason=${n.recovery.reason}`),H={code:n.recovery.code,reason:n.recovery.reason,sessionKey:n.recovery.sessionKey,operationId:n.recovery.operationId,surface:"message_service",...n.recovery.terminalKind?{terminalKind:n.recovery.terminalKind}:{}},!1)};let oe=!0;const se=async(e,n)=>{for(let r=0;;r+=1)try{return await n(),void(oe=!1)}catch(n){if(r>=1)return oe=!0,void a.warn?.(`[im] ${e} failed after terminal redelivery requestId=${m} channel=${t.channelId}: ${formatErrMessage(n)}`);a.warn?.(`[im] ${e} failed; redelivering terminal once requestId=${m} channel=${t.channelId}: ${formatErrMessage(n)}`)}};try{if(W(),e.onNativeRunCompletion&&!e.nativeActiveRunRegistration)throw new Error("native MS Start registration required");const d=l.tryStartInteractive({sessionKey:R,label:"im_chat_message"},"message_service");if(!d.ok){try{await failMessageStream(P,{body:SESSION_BUSY_PUBLIC_MESSAGE,stopReason:"error"})}catch(e){a.warn?.(`[im] session busy terminal write failed channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}return a.warn?.(`[im] session write gate busy sessionKey=${R} channel=${t.channelId} in_reply_to=${t.inboundMessageId} active_operation=${d.activeOperationId??"unknown"}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:"session_busy",cause:"runtime_error"}),!1}if(f=d.token,logChatLatency(a,"claw.session_gate.acquired",m,I),l.bindRun(f,p),Z=o.register(R,j),ee=s.register(R,j),ne=e.approvalStreams?.bindSession(R,j.approvalParts),te=e.questionStreams?.bindSession(R,j.questionParts,{conversationId:t.channelId,replyMessageId:P.id}),D=()=>{ne?.(),te?.()},re=c.register(p,{requestId:m,startedAtMs:I,logger:a}),u){const n=l.snapshot(R);X=e.onNativeRunCompletion?{...e.nativeActiveRunRegistration}:{runtimeConversationUid:t.channelId,runtimeSessionKey:t.channelId,historyGeneration:u.historyGeneration(t.channelId),targetMessageId:t.inboundMessageId,runtimeRunId:p,activeRunRegistrationId:`im:${n?.operationId??p}`},u.activeRuns.register(X,async()=>{const e=`chat_cancel:activeRun:${X.activeRunRegistrationId}`,n=await i.abort(_,e);return n.ok||"already_aborted"===n.reason?"accepted":"terminal_committing"===n.reason||"not_found"===n.reason?"already_terminal":"recovery_required"})}W(),a.info?.(`[im] runtime dispatching requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} origin=${g}`),e.onLifecycleEvent?.({type:"dispatch_start",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId}),e.onNativeRunCompletion&&e.assertNativeTarget&&(await e.assertNativeTarget(),W()),e.onNativeRunCompletion&&e.prepareNativeModel&&(await e.prepareNativeModel(f),W(),await(e.assertNativeTarget?.()),W());const E=t.modelOverrideId;"string"==typeof E&&E.length>0&&R.length>0&&e.applyTurnModel&&(await e.applyTurnModel(R,E),B=!0,W()),F=Date.now(),ae=e.enterTurn?.(R,p),logChatLatency(a,"claw.runtime.invoke",m,I);const S=setTimeout(()=>{const e=Date.now()-F-100;e>=500&&logChatLatency(a,"claw.runtime.event_loop_lag",m,F,{lag_ms:e,phase:"pre_run"})},100);S.unref?.();const $=()=>dispatchRuntimeReplyWithRoute({runtime:n,preparedPrompt:t.dispatchInput,replyRoute:h,replySinks:{im:Y},onDispatchInvoked:n=>{if(x=!0,e.onNativeRunCompletion){v=n;const t=new Promise((e,n)=>{b=e,M=n});t.catch(()=>{}),e.onNativeRunCompletion({runtimeRunId:p,token:f,hostCompletion:n,completion:t})}logChatLatency(a,"claw.runtime.dispatch_returned",m,F)}}),C=ae?ae.run($):$(),N=e.onNativeRunCompletion?await C:await Promise.race([C,O]).finally(()=>{});e.onNativeRunCompletion&&(await v,await w);const q=Q.detectedFailure();if(q)throw new Error(q.diagnosticMessage);if(W(),await V("success"),e.onNativeRunCompletion&&await w,W(),void 0===Y.dispatcher.getTerminalErrorText?.()&&e.htmlDelivery?.assertComplete(),!i.claimTerminal(_,"completion")){if(W(),"cancelling"===i.phase(_))throw new Error("cancellation in progress");throw new Error("terminal outcome already claimed")}if(!await ie("completed"))return await failMessageStream(P,{body:SESSION_RECOVERY_REQUIRED_MESSAGE,stopReason:"error"}).catch(()=>{}),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:SESSION_RECOVERY_REQUIRED_CODE,cause:"runtime_error",...H?{recovery:H}:{}}),!1;const A=Y.dispatcher.getTerminalErrorText?.();if(void 0!==A){let n=!1;const r=classifyAgentRuntimeFailure({raw:A,source:"im_runtime",runtimeKind:"openclaw"});try{await writeRuntimeFailure(P,{body:r.publicMessage,stopReason:messageStopReasonForRuntimeFailure(r),businessErrorCode:r.businessErrorCode})}catch(e){n=!0,a.warn?.(`[im] runtime reply stream error-terminal write outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}return u&&X&&u.activeRuns.markTerminal(X,"failed"),a.warn?.(`[im] runtime dispatch ended with an error terminal requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} counts=${JSON.stringify(N.counts)} terminalWriteFailed=${n} elapsed_ms=${Date.now()-I}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:"runtime_error_terminal_reply",cause:"runtime_error"}),n||await y("",A),!1}let T=!1;try{await P.finalize({stopReason:"end_turn"})}catch(e){T=!0,a.warn?.(`[im] runtime reply stream finalize outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}u&&X&&u.activeRuns.markTerminal(X,"completed");const k={...N.counts,source:j.getSourceCount()};a.info?.(`[im] runtime dispatch completed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} counts=${JSON.stringify(k)} elapsed_ms=${Date.now()-I}`),logChatLatency(a,"claw.turn.terminal",m,I,{outcome:T?"outcome_unknown":"completed",tool_count:k.tool}),e.onLifecycleEvent?.({type:"dispatch_complete",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,counts:k,...T?{terminalWriteFailed:!0}:{}});const L=Y.dispatcher.getAccumulatedBody?.()??"";T||await y(L,"");const U="string"==typeof t.dispatchInput.message?t.dispatchInput.message:"";return maybeRenameImConversationTitle({client:r,conversationId:t.channelId,question:U,answer:L,logger:a}),!0}catch(n){S=n,e.onNativeRunCompletion&&(await(v?.then(()=>{},()=>{})),await w),await V("failure"),e.onNativeRunCompletion&&await w;const r=E.signal.aborted,o=r?E.signal.reason:void 0,s="cancelling"===i.phase(_),c=o??$,l="string"==typeof c&&c.startsWith("chat_cancel");let d="runtime_error";(r||s)&&(d="abort");const p=s||l||r?"cancellation":"completion";if(!i.claimTerminal(_,p))throw a.warn?.(`[im] terminal claim raced requestId=${m} channel=${t.channelId}; best-effort envelope terminal if still streaming`),P.isTerminated?oe=!1:await se("raced terminal write",()=>l?P.cancel({stopReason:"user_stop"}):failMessageStream(P,{body:formatErrMessage(n),stopReason:"error"})),n;const g=l?"cancelled":"error";if(u&&X&&!e.onNativeRunCompletion&&u.activeRuns.markTerminal(X,"cancelled"===g?"cancelled":"failed"),f&&!await ie(g))throw u&&X&&e.onNativeRunCompletion&&u.activeRuns.markTerminal(X,"cancelled"===g?"cancelled":"failed"),l?await se("session recovery cancel",()=>P.cancel({stopReason:"user_stop"})):await se("session recovery terminal write",()=>failMessageStream(P,{body:SESSION_RECOVERY_REQUIRED_MESSAGE,stopReason:"error"})),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:SESSION_RECOVERY_REQUIRED_CODE,cause:d,...H?{recovery:H}:{}}),n;u&&X&&e.onNativeRunCompletion&&u.activeRuns.markTerminal(X,"cancelled"===g?"cancelled":"failed");const h=classifyAgentRuntimeFailure({raw:n,source:"im_runtime",runtimeKind:"openclaw",requestAborted:l}),R=l?h:Q.detectedFailure()??h,b=!x&&n instanceof ModelPreparationError,M=b?MODEL_PREPARATION_FAILED:R.errorCode,C=b?MODEL_PREPARATION_MESSAGE:R.publicMessage;throw l?await se("runtime stream cancel",()=>P.cancel({stopReason:"user_stop"})):await se("runtime stream terminal write",()=>writeRuntimeFailure(P,{body:C,stopReason:messageStopReasonForRuntimeFailure(R),businessErrorCode:b?MODEL_PREPARATION_FAILED:R.businessErrorCode})),a.warn?.(`[im] runtime dispatch failed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} cause=${d} dispatchInvoked=${x} error_code=${M}`),logChatLatency(a,"claw.turn.terminal",m,I,{outcome:d,error_code:M}),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:M,cause:d}),l||oe||await y("",C),n}finally{if(e.onNativeRunCompletion&&(J?b?.(J):(x&&f&&oe&&l.requireRecovery(f,"terminal_not_observed"),M?.(S??new Error(SESSION_RECOVERY_REQUIRED_CODE)))),e.abortSignal?.removeEventListener("abort",K),x&&!J||ae?.close(),A(),re?.(),ee?.(),ne?.(),te?.(),Z?.(),i.unregister(_),B&&e.restoreTurnModel&&R)try{await e.restoreTurnModel(R)}catch(e){a.error?.(`[im] turn model restore failed requestId=${m} sessionKey=${R}: ${formatErrMessage(e)}`)}x?J&&l.release(J):l.releaseBeforeRuntime(f)}};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{claimedSandboxId,identityLaneFromEnvironment}from"./runtime/identity-lane-lease.js";import{createCentralNativeComposition,requireCentralNativeSessionHost}from"./runtime/central-native-composition.js";import{createSandboxNativeTargetLookup,registerSandboxNativeActivation}from"./runtime/sandbox-native-activation.js";import{registerCentralNativeMemoryTools}from"./runtime/central-native-memory.js";import{harnessConnectorToolCaller}from"./connectors/harness-connector-mcp.js";import{registerCentralNativeContextEngine,centralNativeChatEnabled}from"./runtime/central-native-runtime.js";import{relayCentralAskUser}from"./runtime/central-native-interactions.js";import{consumeNativeOutputTool,nativeHtmlDeliveryForRun}from"./runtime/native-output-file-attempt.js";import{uploadNativeOutputFile}from"./upload/upload-file.js";import{nativeOutputToolCallGate}from"./upload/native-output-tool-hook.js";import{NativeInputFilesHttpClient}from"./runtime/native-input-files-http.js";import{fileDeliveryFinalizeDecision}from"./upload/finalize-hook.js";import{resolveConfigWithMeta,mirrorOpenClawConfig}from"./config.js";import{hasRuntimeReplyApi}from"./runtime/reply-router.js";import{PromptRunStore}from"./runtime/prompt-run-store.js";import{createMcpNativeProjectionNudge,fingerprintMcpServers}from"./acp-gateway/mcp-native-projection-nudge.js";import{createImHotPathDeferral}from"./runtime/im-hot-path-deferral.js";import{SessionWriteGate}from"./acp-gateway/session-write-gate.js";import{OpenClawSessionWriteQuiescence}from"./runtime/openclaw-session-write-quiescence.js";import{SessionMutationCoordinator}from"./runtime/session-mutation-coordinator.js";import{scheduleProcessRuntimeRestart}from"./runtime/runtime-restart-scheduler.js";import{createImInboundHandler}from"./im-inbound-handler.js";import{AgentGatewayClient,NodeRuntimeDeliveryPort,agentIdentityFromKeyPair,loadAgentKeyPair,signAgentMessage}from"@beeos-ai/cloud-harness-sdk";import{MessageServiceConversationRunBoundary}from"./runtime/message-service-conversation-run-boundary.js";import{AutomationTurnPolicy}from"./automation/turn-policy.js";import{registerAutomationTools}from"./automation/tools.js";import{extractBeeosConversationIdFromSessionKey}from"./runtime/openclaw-session-key-resolution.js";import{setOpenClawConfigSnapshot}from"./runtime/openclaw-session-model.js";import{BeeosClawMessageClientProcessOwner,createBeeosClawMessageTokenProvider}from"./message-client-composition.js";import{MessageProjectionInboundConsumer}from"./message-projection-inbound-consumer.js";import{MessageClientTerminalStateRecovery}from"./runtime/message-client-terminal-state-recovery.js";import{RuntimeAuthorityMessageBusLifecycle}from"./runtime/runtime-authority-message-bus-lifecycle.js";import{createNativeCloudChatComposition,nativeCloudChatAuthorityFromRuntimeAuthority}from"./runtime/native-cloud-chat-composition.js";import{MSConnectionStatusSnapshot}from"./runtime/ms-connection-status.js";import{FileInboundExecutionJournal}from"./inbound-execution-journal.js";import{completeA2ATask,registerA2ATools,TaskHandleRegistry}from"./a2a/tools.js";import{BEEOS_UPLOAD_TOOL_NAME,BEEOS_UPLOAD_TOOL_SCHEMA,BEEOS_UPLOAD_TOOL_DESCRIPTION,REQUEST_TIMEOUT_MS as BEEOS_UPLOAD_REQUEST_TIMEOUT_MS,executeUpload}from"./upload/tool.js";import{BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,BEEOS_DESKTOP_SCREENSHOT_TOOL_SCHEMA,BEEOS_DESKTOP_SCREENSHOT_TOOL_DESCRIPTION,executeDesktopScreenshot}from"./upload/desktop-screenshot-tool.js";import{BEEOS_LIST_FILES_TOOL_NAME,BEEOS_LIST_FILES_TOOL_SCHEMA,BEEOS_LIST_FILES_TOOL_DESCRIPTION,executeListFiles}from"./files/list-tool.js";import{BEEOS_FETCH_FILE_TOOL_NAME,BEEOS_FETCH_FILE_TOOL_SCHEMA,BEEOS_FETCH_FILE_TOOL_DESCRIPTION,executeFetchFile}from"./files/fetch-tool.js";import{writeUploadToolResult,cleanupUploadToolResultCache}from"./upload/result-cache.js";import{handleFileStage}from"./upload/file-stage.js";import{handleStatusRequest}from"./status.js";import{ACPServer}from"./acp-server.js";import{GatewayClient}from"./gateway-client.js";import{createObsEventWriter}from"./observability.js";import{resolvePluginVersion}from"./plugin-version.js";import{createTerminalWebSocketService}from"./terminal/websocket.js";import{TerminalManager}from"./terminal/session-manager.js";import{readDiscoveryCache,writeDiscoveryCache}from"./discovery-cache.js";import{setClaimedCloudRuntimeInstanceId,setUploadDeps}from"./upload/upload-file.js";import{registerLocalFileExtractor}from"./upload/local-file-extractors.js";import{browserScreenshotExtractor}from"./browser/screenshot-extractor.js";import{deliverableFileExtractor}from"./upload/deliverable-extractor.js";import{observeToolCallForDelivery,rememberDeliveryWorkspace}from"./upload/delivery-observe.js";import{sessionWorkspaceDir}from"./upload/delivery-ledger.js";import{BEEOS_FILE_RESOURCE_ROUTING_RULE}from"./files/beeos-file-uri.js";import{marksFullRuntimeRegistered,planPluginRegistration,replayCachedPluginTools,resolveCapabilityToolReplay}from"./plugin-registration-plan.js";import{buildAppendSystemContext,buildToolRoutingHint,canvasToolBlockReason}from"./prompt-system-context.js";import{CanvasStateManager}from"./canvas/state.js";import{createStaticCanvasHtmlPublisher}from"./canvas/static-html.js";import{CanvasRelayClient}from"./canvas/relay-client.js";import{createSandboxCanvasTokenProvider}from"./canvas/runtime-lease-token.js";import{createCanvasRelayService}from"./canvas/relay-service.js";import{RENDER_UI_TOOL_NAME,RENDER_UI_TOOL_DESCRIPTION,RENDER_UI_TOOL_SCHEMA,CLOSE_UI_TOOL_NAME,CLOSE_UI_TOOL_DESCRIPTION,CLOSE_UI_TOOL_SCHEMA,createRenderUiToolExecutor,createCloseUiHandler,CANVAS_PRESENTATION_GATE,CANVAS_SYSTEM_PROMPT}from"./canvas/tools.js";import{FormSchemaRegistry}from"./surface/form-schema-registry.js";import{buildCronSchemas}from"./surface/cron-schemas.js";import{RENDER_FORM_TOOL_NAME,RENDER_FORM_TOOL_SCHEMA,buildRenderFormDescription,createRenderFormHandler}from"./surface/render-form-tool.js";import{ResourceDescriptorRegistry}from"./surface/resource-descriptor-registry.js";import{CRON_RESOURCE}from"./surface/cron-resource.js";import{generateActionTools}from"./surface/action-tool-generator.js";import{buildThirdPartyChannelSet,isThirdPartyChannel}from"./channel-detection.js";import{registerArouterMediaProviders}from"./media/index.js";import{homedir}from"node:os";import{join}from"node:path";import{RuntimeProductionAuthority,cloudRuntimeTargetInstanceId}from"./runtime/runtime-production-authority.js";import{FileRuntimeCommandJournal}from"./runtime/runtime-command-journal.js";import{FileRuntimePoisonDeliveryJournal}from"./runtime/runtime-poison-delivery-journal.js";import{OpenClawNativeMcpProjection}from"./acp-gateway/openclaw-native-mcp-projection.js";import{LocalEncryptedCredentialReferenceVault}from"./acp-gateway/mcp-credential-reference-port.js";import{AgentGatewayGrantJwksReadinessAdapter,CloudRuntimeServiceTransportReadinessAdapter,RuntimeServiceTransportReadinessAdapter,createRuntimeServiceProductionCandidate}from"./runtime/runtime-service-production-candidate.js";import{fetchRuntimeLeaseAttempt}from"./runtime/message-service-runtime-authenticated-fetch.js";import{MessageServiceCronDeliveryHttpAuthority}from"./runtime/message-service-cron-delivery-http-authority.js";import{AgentMappingRegistry}from"./runtime/agent-mapping-registry.js";import{OpenClawRuntimeProcessOwner}from"./runtime/openclaw-runtime-process-owner.js";import{AgentGatewayHttpProjectionTransport,AgentGatewayTemplateOriginReporter,AgentProjectionProduction,OpenClawAgentProjectionSource}from"./runtime/agent-projection-production.js";import{MessageServiceRunOutputChannel}from"./runtime/message-service-run-output-channel.js";import{AssistantMessageCommitRouter}from"./runtime/assistant-message-commit-router.js";import{OpenClawApprovalBridge}from"./approval/bridge.js";import{APPROVAL_DECISION_MESSAGE_TYPE,isApprovalDocument}from"./approval/protocol.generated.js";import{isQuestionResponseDocument,OpenClawQuestionBridge}from"./question/bridge.js";import{ToolResultObservationRouter}from"./runtime/tool-result-observation-router.js";import{ModelCallObservationRouter,registerModelCallObservationHooks}from"./runtime/model-call-observability.js";import{registerArouterLatencyRouting}from"./runtime/arouter-latency-routing.js";import{createPeerRunOutputRouterFactory}from"./runtime/run-output-composition.js";const PLUGIN_VERSION=resolvePluginVersion();let agentKeys=null,agentGateway=null,sharedCanvasState=null,sharedAcpServer=null;const sharedSessionWriteGate=new SessionWriteGate,sharedPromptRunStore=new PromptRunStore,sharedAutomationTurnPolicy=new AutomationTurnPolicy;let lastOpenclawConfig;const sharedMcpNativeProjectionNudge=createMcpNativeProjectionNudge({getActiveImRunCount:()=>sharedPromptRunStore.size(),nudge:()=>{sharedAcpServer?.nudgeMcpNativeProjection()}}),sharedImHotPathDeferral=createImHotPathDeferral({getActiveImRunCount:()=>sharedPromptRunStore.size()});sharedPromptRunStore.setOnBecameIdle(()=>{sharedMcpNativeProjectionNudge.flushIfIdle({fingerprint:fingerprintMcpServers(lastOpenclawConfig)}),sharedImHotPathDeferral.notifyIdle()});const sharedAssistantMessageCommitRouter=new AssistantMessageCommitRouter,sharedToolResultObservationRouter=new ToolResultObservationRouter;let approvalLogger;const sharedApprovalBridge=new OpenClawApprovalBridge({request:(e,t)=>sharedGatewayClient?sharedGatewayClient.request(e,t):Promise.reject(new Error("Not connected to Gateway")),logger:{info:e=>approvalLogger?.info?.(e),warn:e=>approvalLogger?.warn?.(e)}}),sharedQuestionBridge=new OpenClawQuestionBridge({request:(e,t)=>sharedGatewayClient?sharedGatewayClient.request(e,t):Promise.reject(new Error("Not connected to Gateway")),logger:{info:e=>approvalLogger?.info?.(e),warn:e=>approvalLogger?.warn?.(e)}}),sharedModelCallObservationRouter=new ModelCallObservationRouter;let sharedSessionMutationCoordinator,sharedCentralPrompt,sharedRuntimeAuthority,sharedNativeChatService,sharedNativeCloudChat,sharedWriteObs=()=>{};const sharedMSConnectionStatus=new MSConnectionStatusSnapshot,sharedAgentMappings=new AgentMappingRegistry;let sharedGatewayClient,sharedRuntimeOwner,sharedAgentProjection,sharedRuntimeAgentCapabilities,sharedMcpProjection,sharedMcpCredentialVault;const sharedMessageClientOwner=new BeeosClawMessageClientProcessOwner;let sharedActiveMessageConsumer,sharedInboundExecutionJournal;const sharedTerminalManager=new TerminalManager;let _initializing=!1,_pluginRegisteredAt=0,_fullRuntimeRegistered=!1;const cachedCapabilityTools=[];let rawRegisterTool,wrappedRegisterTool;const cachedRuntimeServices=[],cachedRuntimeHooks=[];let rawRegisterService,wrappedRegisterService,rawOn,wrappedOn;function cacheRuntimeRegistrations(e){const t=e.registerService===wrappedRegisterService?rawRegisterService:e.registerService;if(rawRegisterService=t,wrappedRegisterService=r=>{cachedRuntimeServices.push(r),t.call(e,r)},e.registerService=wrappedRegisterService,cachedRuntimeServices.length=0,cachedRuntimeHooks.length=0,e.on){const t=e.on===wrappedOn?rawOn:e.on;rawOn=t,wrappedOn=(...r)=>{cachedRuntimeHooks.push(r),t.call(e,...r)},e.on=wrappedOn}}function replayRuntimeRegistrations(e){const t=e.registerService===wrappedRegisterService?rawRegisterService:e.registerService,r=e.on===wrappedOn?rawOn:e.on;for(const t of cachedRuntimeHooks)r.call(e,...t);for(const r of cachedRuntimeServices)t.call(e,r)}const ensureRegisterToolCache=e=>{const t=e.registerTool===wrappedRegisterTool?rawRegisterTool:e.registerTool;rawRegisterTool=t.bind(e),wrappedRegisterTool=(e,t)=>(cachedCapabilityTools.push({tool:e,options:t}),rawRegisterTool(e,t)),e.registerTool=wrappedRegisterTool};function agentKeyPairToIdentity(e){return{publicKeyBase64:()=>Buffer.from(e.publicKey).toString("base64"),sign:async t=>signAgentMessage(t,e.privateKey)}}let sharedPluginContext=null,unhandledRejectionObserverInstalled=!1;function installUnhandledRejectionObserver(e,t,r){unhandledRejectionObserverInstalled||(unhandledRejectionObserverInstalled=!0,process.on("unhandledRejection",r=>{const o=r instanceof Error?r.message:String(r),a=r instanceof Error?r.stack:void 0;e.logger.error?.(`[beeos-claw] unhandledRejection: ${o}${a?`\n${a}`:""}`),t({component:"plugin",domain:"fatal",name:"unhandled_rejection",severity:"error",summary:o,error:{code:"unhandled_rejection",message:o,...a?{stack:a}:{}}})}),process.on("uncaughtException",r=>{const o=r instanceof Error?r.message:String(r);e.logger.error?.(`[beeos-claw] uncaughtException: ${r instanceof Error?r.stack??r.message:String(r)}`),t({component:"plugin",domain:"fatal",name:"uncaught_exception",severity:"error",summary:o,error:{code:"uncaught_exception",message:o}})}))}function initializePlugin(e){let t,r;try{t=e.runtime?.config?.loadConfig?.()}catch{}try{r=resolveConfigWithMeta({pluginConfig:e.pluginConfig??{},openclawConfig:t})}catch(t){return e.logger.error?.(`[beeos-claw] Failed to resolve config: ${t instanceof Error?t.message:String(t)}`),null}const o=r.config,a=buildThirdPartyChannelSet(t);a.size>0&&e.logger.info?.(`[beeos-claw] Third-party channels detected: ${[...a].join(", ")}`);const n=o.log.enabled?createObsEventWriter({dir:o.log.dir,redaction:{gatewayToken:o.gateway.token},logger:e.logger}):()=>{};n({component:"plugin",domain:"lifecycle",name:"lifecycle.startup",severity:"info",payload:{pluginVersion:PLUGIN_VERSION,pid:process.pid,nodeVersion:process.version,cwd:process.cwd()}}),n({component:"plugin",domain:"config",name:"config.resolved",severity:"info",payload:{config:o,sources:r.sources,openclawConfigPath:r.openclawConfigPath}});for(const t of r.validation)n({component:"plugin",domain:"config",name:"config.validation",severity:t.severity,summary:t.message,error:{code:t.code,message:t.message,nextSteps:t.nextSteps}}),"error"===t.severity?e.logger.error?.(`[beeos-claw] ${t.message}`):e.logger.warn?.(`[beeos-claw] ${t.message}`);if(r.validation.some(e=>"error"===e.severity)&&e.logger.error?.("[beeos-claw] Plugin has configuration errors — some features may not work."),o.keyFile)try{agentKeys=loadAgentKeyPair(o.keyFile),agentGateway=o.agentGatewayUrl?new AgentGatewayClient({baseUrl:o.agentGatewayUrl,identity:agentIdentityFromKeyPair(agentKeys),onRetry:({method:t,path:r,attempt:o,delayMs:a,error:n})=>e.logger.warn?.(`[beeos-claw] Agent Gateway ${t} ${r} retry ${o} in ${a}ms: ${n instanceof Error?n.message:String(n)}`)}):null;const t=Buffer.from(agentKeys.publicKey).toString("base64");e.logger.info?.(`[beeos-claw] v${PLUGIN_VERSION} registering (publicKey: ${t})`)}catch(t){e.logger.warn?.(`[beeos-claw] Failed to load agent key pair: ${t}`),e.logger.info?.(`[beeos-claw] v${PLUGIN_VERSION} registering (no key pair — signed requests disabled)`)}else e.logger.info?.(`[beeos-claw] v${PLUGIN_VERSION} registering (no keyFile configured)`);return agentGateway&&(setUploadDeps({gateway:agentGateway,logger:e.logger}),registerLocalFileExtractor(browserScreenshotExtractor),registerLocalFileExtractor(deliverableFileExtractor),e.logger.info?.("[beeos-claw] Upload deps + local file extractors registered")),lastOpenclawConfig=t,sharedWriteObs=n,setOpenClawConfigSnapshot(t),{cfg:o,writeObs:n,thirdPartyChannels:a,openclawConfig:t}}function registerUploadTools(e,t,r){const{cfg:o,writeObs:a}=t,n=Boolean(pluginCloudRuntimeTarget(e));if(n){if(!e.on)throw new Error("native output Files Host hook unavailable");e.on("before_tool_call",(t,r)=>nativeOutputToolCallGate(t,r,e.logger))}cleanupUploadToolResultCache().catch(t=>{e.logger.warn?.(`[beeos_upload_file] cache cleanup failed on startup: ${String(t)}`)}),e.registerTool(t=>({name:BEEOS_UPLOAD_TOOL_NAME,description:BEEOS_UPLOAD_TOOL_DESCRIPTION,parameters:BEEOS_UPLOAD_TOOL_SCHEMA,async execute(r,i,s){const l=n?consumeNativeOutputTool(r):void 0,c=t.workspaceDir??sessionWorkspaceDir(t.sessionKey),u=await executeUpload(i,agentGateway,s,l?(e,t)=>uploadNativeOutputFile(e,o.agentGatewayUrl,l,t,s,BEEOS_UPLOAD_REQUEST_TIMEOUT_MS):void 0,e.logger,l?c:void 0);return e.logger.debug?.(`[beeos_upload_file] toolCallId=${r} ok=${u.ok}`),a({component:"upload-tool",domain:"tool",name:u.ok?"upload.success":"upload.failure",severity:u.ok?"info":"warn",payload:{toolCallId:r,ok:u.ok,fileCount:u.files?.length??0,error:u.error}}),(async t=>{try{await writeUploadToolResult(r,BEEOS_UPLOAD_TOOL_NAME,t),await cleanupUploadToolResultCache()}catch(t){e.logger.warn?.(`[beeos_upload_file] persist cache failed toolCallId=${r}: ${String(t)}`)}return t})(u)}}),{name:BEEOS_UPLOAD_TOOL_NAME}),e.registerTool({name:BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,description:BEEOS_DESKTOP_SCREENSHOT_TOOL_DESCRIPTION,parameters:BEEOS_DESKTOP_SCREENSHOT_TOOL_SCHEMA,async execute(t,r,o){e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${t} params=${JSON.stringify(r)}`);const n=await executeDesktopScreenshot(r,agentGateway,o);return e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${t} ok=${n.ok}`),a({component:"desktop-screenshot-tool",domain:"tool",name:n.ok?"desktop_screenshot.success":"desktop_screenshot.failure",severity:n.ok?"info":"warn",payload:{toolCallId:t,ok:n.ok,path:n.path,fileCount:n.files?.length??0,error:n.error}}),(async r=>{try{await writeUploadToolResult(t,BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,r),await cleanupUploadToolResultCache()}catch(r){e.logger.warn?.(`[beeos_desktop_screenshot] persist cache failed toolCallId=${t}: ${String(r)}`)}return r})(n)}}),e.registerHttpRoute({path:"/beeos/files/stage",auth:"gateway",async handler(e,r){await handleFileStage(e,r,t.cfg)}}),e.registerHttpRoute({path:"/beeos/status",auth:"plugin",handler(e,t){handleStatusRequest(e,t,{publicKey:agentKeys?.publicKey??null,pluginVersion:PLUGIN_VERSION})}}),e.registerTool({name:BEEOS_LIST_FILES_TOOL_NAME,description:BEEOS_LIST_FILES_TOOL_DESCRIPTION,parameters:BEEOS_LIST_FILES_TOOL_SCHEMA,async execute(t,r,o){e.logger.debug?.(`[beeos_list_files] toolCallId=${t} params=${JSON.stringify(r)}`);const n=await executeListFiles(r,agentGateway,o);return a({component:"file-list-tool",domain:"tool",name:n.ok?"list_files.success":"list_files.failure",severity:n.ok?"info":"warn",payload:{toolCallId:t,ok:n.ok,fileCount:n.files?.length??0,error:n.error}}),n}}),e.registerTool(t=>({name:BEEOS_FETCH_FILE_TOOL_NAME,description:BEEOS_FETCH_FILE_TOOL_DESCRIPTION,parameters:BEEOS_FETCH_FILE_TOOL_SCHEMA,async execute(r,i,s){e.logger.debug?.(`[beeos_fetch_file] toolCallId=${r} params=${JSON.stringify(i)}`);const l=await executeFetchFile(i,agentGateway,{signal:s,workspaceDir:t.workspaceDir,...n?{native:{gatewayUrl:o.agentGatewayUrl,capability:consumeNativeOutputTool(r)}}:{}});return a({component:"file-fetch-tool",domain:"tool",name:l.ok?"fetch_file.success":"fetch_file.failure",severity:l.ok?"info":"warn",payload:{toolCallId:r,ok:l.ok,path:l.path,size:l.size,error:l.error}}),l}}),{name:BEEOS_FETCH_FILE_TOOL_NAME})}function registerServices(e,t,r){const{cfg:o,writeObs:a,thirdPartyChannels:n}=t,i=centralNativeChatEnabled()?requireCentralNativeSessionHost(e.runtime):void 0;if(sharedAutomationTurnPolicy.disable(),"function"==typeof e.on)try{e.on("before_tool_call",(e,t)=>sharedAutomationTurnPolicy.check(e.toolName,{sessionKey:t?.sessionKey,runId:t?.runId??e.runId}),{priority:100}),sharedAutomationTurnPolicy.enable()}catch{e.logger.warn?.("[beeos-claw] Automation Wake disabled: tool guard unavailable")}if("function"!=typeof e.on){if(o.messageBus.enabled)throw new Error("openclaw_before_message_write_hook_unavailable")}else registerModelCallObservationHooks((t,r)=>e.on(t,r),sharedModelCallObservationRouter),e.on("before_message_write",(t,r)=>{const o=t.sessionKey??r.sessionKey;if(!o)return void e.logger.debug?.("[before_message_write] ignored assistant write without sessionKey");sharedAssistantMessageCommitRouter.route(o,t.message)||e.logger.debug?.(`[before_message_write] no active IM commit target sessionKey=${o} active_targets=${sharedAssistantMessageCommitRouter.size()}`)}),e.on("before_tool_call",(e,t)=>{if("ask_user"!==(e.toolName||t.toolName))return;const r={sessionKey:t.sessionKey,runId:t.runId??e.runId,toolCallId:t.toolCallId??e.toolCallId};sharedQuestionBridge.observeAskUser(r),relayCentralAskUser((e,t)=>sharedGatewayClient?sharedGatewayClient.request(e,t):Promise.reject(new Error("Not connected to Gateway")),r).catch(e=>approvalLogger?.warn?.(`[question] central relay failed: ${e instanceof Error?e.message:String(e)}`))}),e.on("after_tool_call",(t,r)=>{const o=r.sessionKey,a=t.toolCallId??r.toolCallId,n=t.toolName||r.toolName;if(t.runId&&r.runId&&t.runId!==r.runId||t.toolCallId&&r.toolCallId&&t.toolCallId!==r.toolCallId||nativeHtmlDeliveryForRun(t.runId??r.runId)?.observe(n,t.params,t.result,Boolean(t.error),a),!o||!a||!n)return void e.logger.debug?.(`[after_tool_call] ignored structured result without correlation sessionKey=${o??"missing"} toolCallId=${a??"missing"}`);observeToolCallForDelivery(t,o);sharedToolResultObservationRouter.route(o,{toolCallId:a,toolName:n,rawResult:t.result,isError:Boolean(t.error)})||e.logger.debug?.(`[after_tool_call] no active IM observation target sessionKey=${o} active_targets=${sharedToolResultObservationRouter.size()}`)});const s=agentKeys?Buffer.from(agentKeys.publicKey).toString("base64"):void 0,l=join(process.env.OPENCLAW_HOME||join(homedir(),".openclaw"),"beeos"),c=sharedInboundExecutionJournal??=new FileInboundExecutionJournal(join(l,"inbound-execution-journal.v1.jsonl"));sharedMcpProjection??=new OpenClawNativeMcpProjection,!sharedMcpCredentialVault&&agentKeys&&s&&(sharedMcpCredentialVault=new LocalEncryptedCredentialReferenceVault(join(l,"mcp-credential-vault.json"),s,agentKeys.privateKey));const u=pluginCloudRuntimeTarget(e);if(setClaimedCloudRuntimeInstanceId(u),u&&(!agentKeys||!agentGateway))throw new Error("Cloud runtime authority requires an agent identity and gateway transport");const d=sharedRuntimeAuthority?.cloudTargetInstanceId;if(d&&u&&d!==u)throw new Error("Cloud runtime authority target changed during process lifetime");if(sharedRuntimeAuthority&&!d&&u&&sharedRuntimeAuthority.bindCloudTarget(u),!sharedRuntimeAuthority&&agentKeys&&agentGateway&&(sharedRuntimeAuthority=new RuntimeProductionAuthority({stateDirectory:l,gateway:agentGateway,keys:agentKeys,targetInstanceId:u,logger:e.logger,getMSConnectionStatus:e=>sharedMSConnectionStatus.get(e),identityLane:identityLaneFromEnvironment()})),sharedGatewayClient||(sharedGatewayClient=new GatewayClient({url:o.gateway.url,token:o.gateway.token||"",clientId:o.gateway.clientId,openclawCanvasCompat:!!o.openclawCanvasCompat,retry:{baseMs:o.retry.baseMs,maxMs:o.retry.maxMs,maxAttempts:o.retry.maxAttempts}}),sharedGatewayClient.on("gateway-event",(e,t)=>{sharedApprovalBridge.onGatewayEvent(e,t),sharedQuestionBridge.onGatewayEvent(e,t)})),approvalLogger??=e.logger,sharedRuntimeAgentCapabilities??={canvas:o.canvasEnabled,terminal:!1,webSsh:!1,fileSystem:!0,image:!0,audio:!1,mcp:!0,cron:!0,streaming:!0,pushNotifications:o.messageBus.enabled,...o.messageBus.enabled&&sharedAutomationTurnPolicy.isReady()&&agentGateway?{automationWake:!0}:{}},!sharedAgentProjection&&sharedRuntimeAuthority&&agentGateway){const t=sharedRuntimeAuthority;sharedAgentProjection=new AgentProjectionProduction({authority:t,stateFile:join(t.stateDirectory,"runtime-agent-projection.json"),journal:t.journal,identities:t.identities,source:new OpenClawAgentProjectionSource(()=>sharedGatewayClient),transport:new AgentGatewayHttpProjectionTransport({gateway:agentGateway,getRuntimeLeaseCredential:e=>{const r=t.authorityLease;if(!r||r.instanceId!==e.instanceId||r.leaseId!==e.leaseId||r.runtimeEpoch!==e.runtimeEpoch||r.handlerIdentity!==e.handlerIdentity)throw new Error("agent projection fenced by current runtime lease");return r.runtimeLeaseCredential},onAccepted:t=>{0!==t.size&&sharedAgentMappings.replace(t).catch(t=>{e.logger.warn?.("[agent-projection] mapping publication failed: "+(t instanceof Error?t.message:String(t)))})}}),capabilities:sharedRuntimeAgentCapabilities,logger:e.logger})}sharedRuntimeOwner??=new OpenClawRuntimeProcessOwner(sharedGatewayClient,sharedAgentProjection,e.logger);const g=sharedRuntimeOwner;sharedSessionMutationCoordinator??=new SessionMutationCoordinator(sharedSessionWriteGate,new OpenClawSessionWriteQuiescence(e.logger,{agentId:o.gateway.agentId||"main",...i?{nativeWritersQuiescent:e=>i.nativeWritersQuiescent({sessionKey:e})}:{}}),e.logger,{onRecoveryRequired:t=>{scheduleProcessRuntimeRestart(t,e.logger)}});const m=sharedSessionMutationCoordinator;if(i&&!sharedCentralPrompt){if(!sharedRuntimeAuthority?.cloudTargetInstanceId)throw new Error("central native chat requires the provisioned Cloud runtime authority");sharedCentralPrompt=createCentralNativeComposition({runtime:e.runtime,host:i,gatewayOrigin:o.agentGatewayUrl,stateDirectory:l,authority:sharedRuntimeAuthority,coordinator:m,logger:e.logger})}if(i&&registerCentralNativeMemoryTools(e),!sharedAcpServer){const t=sharedRuntimeAuthority&&agentGateway?new AgentGatewayTemplateOriginReporter({gateway:agentGateway}):void 0;sharedAcpServer=new ACPServer(o,e.logger,m,a,agentGateway??void 0,s,n,sharedTerminalManager,sharedRuntimeAuthority,void 0,sharedMcpProjection,sharedMcpCredentialVault,{gateway:g.client,agentProjection:sharedAgentProjection,markAgentProjectionDirty:()=>sharedAgentProjection?.markDirty(),templateOriginReporter:t,agentMappings:sharedAgentMappings,agentCapabilities:sharedRuntimeAgentCapabilities,createRunOutputRouter:createPeerRunOutputRouterFactory(new MessageServiceRunOutputChannel({getClient:()=>sharedMessageClientOwner.current?.client??null,logger:e.logger,writeObs:a})),runExclusive:(t,r,o)=>sharedImHotPathDeferral.runExclusive(t,r,e.logger,o)})}const p=sharedAcpServer,h=()=>sharedAgentMappings.snapshot()?.values().next().value;r.current=p,sharedMcpNativeProjectionNudge.request({registrationMode:e.registrationMode,fingerprint:fingerprintMcpServers(t.openclawConfig),logger:e.logger});const y=sharedPromptRunStore,{enabled:v,principalId:w,a2aEnabled:f}=o.messageBus;let C;!u&&o.agentGatewayUrl&&agentKeys&&(C=createBeeosClawMessageTokenProvider({agentGatewayUrl:o.agentGatewayUrl,identity:agentKeyPairToIdentity(agentKeys)}));const R=process.env.MESSAGE_RUNTIME_DELIVERY_KEY?.trim(),b=w||process.env.BEEOS_PRINCIPAL_ID||"",S=C?sharedMessageClientOwner.configure({tokenProvider:C,identityId:b,...o.messageBus.serviceUrl?{serviceUrl:o.messageBus.serviceUrl}:{},logger:e.logger,...sharedRuntimeAuthority&&R?{runtimeDelivery:{scopedDeliveryKey:R,authority:{currentLease:()=>{const e=sharedRuntimeAuthority?.authorityLease,t=sharedRuntimeAuthority?.currentConsumerBinding();return e&&t?{...e,journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}:null}}}}:{}}):void 0,E=u&&o.messageBus.serviceUrl&&sharedRuntimeAuthority?new NodeRuntimeDeliveryPort({serviceOrigin:async()=>o.messageBus.serviceUrl},{currentLease:()=>{const e=sharedRuntimeAuthority?.authorityLease,t=sharedRuntimeAuthority?.currentConsumerBinding();return e&&t&&e.instanceId===u?{...e,journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}:null},subscribeAuthority:e=>sharedRuntimeAuthority.subscribeAuthority(e)}):void 0;attachNativeCloudChat(e,o);const O=sharedRuntimeAuthority,_=o.messageBus.serviceUrl;S&&O&&_&&R?p.setCronConversationDelivery({deliver:async e=>{const t=O.authorityLease;if(!t)throw new Error("current runtime authority lease unavailable for cron delivery");const r=new MessageServiceCronDeliveryHttpAuthority({messageServiceUrl:_,scopedDeliveryKey:R,fetchAuthorized:(e,t)=>fetchRuntimeLeaseAttempt(e,t??{})});return await r.deliver({...e,runtimeLeaseCredential:t.runtimeLeaseCredential})}}):p.setCronConversationDelivery(void 0);const A=sharedRuntimeAuthority?.journal??new FileRuntimeCommandJournal(join(l,"runtime-command-journal.json"),void 0,void 0,{onMaintenanceError:t=>e.logger.error?.(`[runtime-journal] event=checkpoint_failed trigger=threshold error=${t instanceof Error?t.message:String(t)}`)}),I=g.createRegistrationToken();e.registerService({id:"beeos-acp",async start(){const t=Date.now(),r=_pluginRegisteredAt?t-_pluginRegisteredAt:-1;e.logger.info?.(`[beeos-claw] beeos-acp service start() begin, sincePluginRegister=${r}ms, bridge.url=${o.bridge.url||"(empty)"}`);const a=await createRuntimeServiceProductionCandidate({...agentGateway?{authorizationAdapter:new AgentGatewayGrantJwksReadinessAdapter({gateway:agentGateway})}:{},onGrantJwksWarm:t=>{t.ready?e.logger.info?.("[beeos-claw] Gateway grant keyset loaded"):e.logger.warn?.(`[beeos-claw] Gateway grant keyset not ready yet (attempt ${t.attempt}): ${t.error instanceof Error?t.error.message:String(t.error)}`)},...S&&agentGateway&&R?{transportAdapter:new RuntimeServiceTransportReadinessAdapter({gateway:agentGateway,messageService:S.nodeTransport,messageClient:S.client,configuredServiceUrl:o.messageBus.serviceUrl,scopedDeliveryKey:R})}:{},...E&&agentGateway&&o.messageBus.serviceUrl?{cloudTransportAdapter:new CloudRuntimeServiceTransportReadinessAdapter({gateway:agentGateway,configuredServiceUrl:o.messageBus.serviceUrl,runtimeDelivery:E,...sharedCentralPrompt?{centralPrompt:sharedCentralPrompt}:{},...sharedNativeCloudChat?{sessionNewConversation:sharedNativeCloudChat.sessionNewConversation,nativePrompt:{http:sharedNativeCloudChat.http,inputFiles:new NativeInputFilesHttpClient(o.agentGatewayUrl,()=>sharedRuntimeAuthority.authorityLease,(e,t)=>fetch(e,t)),runBoundary:new MessageServiceConversationRunBoundary({transport:{start:e=>E.startConversationRun(e),finish:e=>E.finishConversationRun(e)}}),host:{htmlDeliveryEnabled:o.canvasEnabled,resolveNativePromptSessionKey:(e,t)=>p.resolveNativePromptSessionKey(e,t),prepareNativePromptModel:(e,t,r)=>p.prepareNativePromptModel(e,t,r),runtime:e.runtime,pluginConfig:o,logger:e.logger,promptRunStore:y,assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,approvalStreams:sharedApprovalBridge,questionStreams:sharedQuestionBridge,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:m,abortTransport:{chatAbort:(e,t)=>p.chatAbort(e,t)},activeRunAuthority:p.getActiveRunAuthority(),waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{})}}}:{}})}:{},commandJournal:A,poisonJournal:new FileRuntimePoisonDeliveryJournal(join(l,"runtime-poison-deliveries.json")),onConsumerDeliveryError:t=>{const r=null!==t&&"object"==typeof t?t:{},o=e=>"string"==typeof e&&e.length>0&&e.length<=256&&!/[\u0000-\u001f\u007f]/.test(e)?JSON.stringify(e):JSON.stringify("unavailable"),a="string"==typeof r.code&&/^[A-Za-z0-9_.:-]{1,64}$/.test(r.code)?r.code:"unavailable",n="number"==typeof r.status&&Number.isInteger(r.status)&&r.status>=100&&r.status<=599?String(r.status):"unavailable";e.logger.error?.(`[runtime-service] delivery worker failed before acknowledgement; delivery retained for retry: operation_id=${o(r.operationId)} delivery_id=${o(r.deliveryId)} code=${a} status=${n}`)},onConsumerLeaseStarvation:({starvedForMs:t,recovered:r})=>{const o=Math.round(t/1e3);r?e.logger.info?.(`[runtime-service] runtime authority lease restored after ${o}s without delivery reads`):e.logger.warn?.(`[runtime-service] no runtime authority lease for ${o}s; delivery reads suspended, queued runtime operations (model switch, session control) will not be consumed`)},onConsumerRequestFailure:t=>e.logger.error?.(`[runtime-service] request failed operationId=${t.operationId} method=${t.method}: ${t.error instanceof Error?t.error.stack??t.error.message:String(t.error)}`)});if(sharedRuntimeAuthority?.setRuntimeServiceMethods("ready"===a.status?a.serviceMethods:[]),sharedRuntimeAuthority?.setRuntimeResourceBindingContractRevision("ready"===a.status?a.resourceBindingContractRevision:void 0),p.setRuntimeRpcConsumerFactory("ready"===a.status?a.factory:void 0),"unavailable"===a.status?e.logger.warn?.("[runtime-service] capability fenced: "+a.blockers.map(e=>e.id).join(",")):a.capabilityBlockers.length&&e.logger.warn?.("[runtime-service] method capability fenced: "+a.capabilityBlockers.map(e=>e.method).join(",")),!o.bridge.url&&agentGateway){const t=Date.now(),r=await agentGateway.bridge.config();if(e.logger.info?.(`[beeos-claw] bridge discovery took ${Date.now()-t}ms result=${r?.url??"null"}`),r)o.bridge.url=r.url,writeDiscoveryCache({bridge:{url:r.url,discoveredAt:Date.now()}}),e.logger.info?.(`[beeos-claw] Bridge URL discovered from Agent Gateway: ${r.url}`);else{const t=readDiscoveryCache();t?.bridge?.url?(o.bridge.url=t.bridge.url,e.logger.info?.(`[beeos-claw] Bridge URL from cache (GW unreachable): ${t.bridge.url}`)):e.logger.debug?.("[beeos-claw] Bridge URL not available (no GW, no cache) — bridge disabled")}}await g.acquire(I);try{await p.start(o.bridge.url||void 0)}catch(e){throw await g.release(I),e}e.logger.info?.(`[beeos-claw] ACP Server started (total service start: ${Date.now()-t}ms)`)},async stop(){try{await g.release(I)}finally{await p.stop()}await A.checkpoint(),e.logger.info?.("[runtime-service] command journal checkpoint completed"),e.logger.info?.("[beeos-claw] ACP Server stopped")}});if(v&&void 0!==C&&C){const t=sharedMessageClientOwner.createRegistrationToken(),r=async(e,t)=>{const r=await C(e);if(!r.identityId||r.identityId!==e)throw new Error("Message SDK token identity did not match the current runtime authority");return{principalId:e,runtimeEpoch:t}},o=(e,t,r)=>({getLocalAgentId:()=>t,resolveLocalAgentId:e=>e===r?t:void 0,getDefaultPlatformAgent:()=>({instanceId:e.principalId}),ensureImInboundSession:(e,t,r,o)=>{p.ensureImInboundSession(e,t,r,o)},chatAbort:(e,t)=>p.chatAbort(e,t)}),n=sharedRuntimeAuthority?new RuntimeAuthorityMessageBusLifecycle({authority:sharedRuntimeAuthority,logger:e.logger,bus:{connect:async n=>{await sharedMessageClientOwner.acquire(t,async t=>{const i=await r(n.instanceId,n.runtimeEpoch),s=t.client,l={leaseId:n.leaseId,runtimeEpoch:n.runtimeEpoch};sharedMSConnectionStatus.bind(l);const u=new Map,d=new MessageProjectionInboundConsumer({client:s,bindings:()=>{const t=sharedRuntimeAuthority?.authorityLease;if(!t||t.instanceId!==i.principalId||t.runtimeEpoch!==i.runtimeEpoch)return[];const r=sharedAgentMappings.snapshot();return r?[...r.entries()].flatMap(([r,n])=>{if(!n.id||n.instanceId!==i.principalId)return[];let l=u.get(n.id);return l&&l.localAgentId===r||(l={localAgentId:r,inbound:createImInboundHandler({automationTurnPolicy:sharedAutomationTurnPolicy,runtime:e.runtime,pluginConfig:e.pluginConfig,client:s,localServer:o(i,r,n.id),promptRunStore:y,waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{}),assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,approvalStreams:sharedApprovalBridge,questionStreams:sharedQuestionBridge,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:m,logger:e.logger,writeObs:a,principalIdOverride:i.principalId,activeRunAuthority:p.getActiveRunAuthority(),applyTurnModel:(e,t)=>p.applyImTurnModel(e,t),restoreTurnModel:e=>p.restoreImTurnModel(e),...agentGateway?{completeA2ATask:(t,r,o)=>completeA2ATask({gateway:agentGateway,logger:e.logger},t,r,o)}:{}})},u.set(n.id,l)),[{principalId:i.principalId,targetAgentId:n.id,runtimeEpoch:t.runtimeEpoch,inbound:l.inbound}]}):[]},executionJournal:c,logger:e.logger}),g=sharedAgentMappings.subscribe(()=>{sharedActiveMessageConsumer===d&&d.refresh()}),h=sharedRuntimeAuthority?.subscribeAuthority(()=>{sharedActiveMessageConsumer===d&&d.refresh()})??(()=>{}),v=new MessageClientTerminalStateRecovery({logger:e.logger,isCurrent:()=>{if(sharedActiveMessageConsumer!==d)return!1;const e=sharedRuntimeAuthority?.authorityLease;return null!=e&&e.instanceId===i.principalId&&e.runtimeEpoch===i.runtimeEpoch&&e.leaseId===n.leaseId&&e.handlerIdentity===n.handlerIdentity},reconnect:async()=>{if("failed"===s.getSnapshot().connection){await s.connect();try{await p.rebindRuntimeDelivery()}catch(t){e.logger.warn?.(`[beeos-claw] runtime Service delivery rebind failed after MessageClient recovery: ${t instanceof Error?t.message:String(t)}`)}}}});let w=s.getSnapshot().connection;sharedMSConnectionStatus.setIfCurrent(l,w);const f=s.subscribe(()=>{const t=s.getSnapshot();t.connection!==w&&(w=t.connection,sharedMSConnectionStatus.setIfCurrent(l,t.connection),"connected"===t.connection?(v.notifyConnected(),e.logger.info?.(`[beeos-claw] connection transport=message_service_realtime state=connected localAgentId=${p.getLocalAgentId()} principalId=${i.principalId}`)):"failed"===t.connection?(e.logger.warn?.(`[beeos-claw] connection transport=message_service_realtime state=failed principalId=${i.principalId} recoveryError=${t.recoveryError??"unknown"}`),v.notifyFailed()):"disconnected"!==t.connection&&"reconnecting"!==t.connection||e.logger.warn?.(`[beeos-claw] connection transport=message_service_realtime state=${t.connection} principalId=${i.principalId}; SDK owns reconnect/recovery`))});sharedActiveMessageConsumer=d,d.start();try{await s.connect()}catch(e){throw sharedActiveMessageConsumer===d&&(sharedActiveMessageConsumer=void 0),sharedMSConnectionStatus.resetIfCurrent(l),v.dispose(),await d.stop(),g(),h(),f(),await s.disconnect().catch(()=>{}),e}try{await p.rebindRuntimeDelivery()}catch(t){e.logger.warn?.(`[beeos-claw] runtime Service delivery rebind failed after MessageClient connect: ${t instanceof Error?t.message:String(t)}`)}return async()=>{sharedActiveMessageConsumer===d&&(sharedActiveMessageConsumer=void 0),sharedMSConnectionStatus.resetIfCurrent(l),v.dispose(),await d.stop(),h(),f(),await s.disconnect(),e.logger.info?.("[beeos-claw] MessageClient disconnected")}})},disconnect:async()=>{await sharedMessageClientOwner.release(t)}}}):void 0;e.registerService({id:"beeos-message-bus",async start(){n?n.start():e.logger.warn?.("[beeos-claw] Message bus requires runtime authority; waiting is unavailable without Agent Gateway runtime identity")},async stop(){await(n?.stop())}})}else v?e.logger.warn?.("[beeos-claw] Message bus enabled but Agent Gateway token provider is unavailable — disabled"):e.logger.info?.(`[beeos-claw] Message bus disabled (enabled=${v})`);if(o.messageBus.enabled&&u&&!sharedNativeCloudChat&&e.logger.warn?.("[beeos-claw] Cloud message bus enabled but native composition unavailable (messageBus.serviceUrl or runtime authority missing) — disabled"),!1!==f&&agentGateway){const t=e=>p.getGatewaySessionKeyForToolCall(e),r=e=>p.getMentionsForToolCall(e),o=(e,t)=>{p.broadcastNotification(e,t)},a=new TaskHandleRegistry;registerA2ATools(e,{gateway:agentGateway,logger:e.logger},a,t,r,o,()=>h()?.instanceId),e.logger.info?.("[beeos-claw] A2A tools registered (beeos_discover_agents, beeos_call_agent) via REST")}if(agentGateway&&(registerAutomationTools(e,{gateway:agentGateway,callConnectorTool:harnessConnectorToolCaller(),logger:e.logger,getDefaultAgent:()=>{const e=h();return e?{id:e.id,instanceId:e.instanceId}:void 0},getCurrentConversationId:e=>{const t=p.getGatewaySessionKeyForToolCall(e);return t?extractBeeosConversationIdFromSessionKey(t):void 0}}),e.logger.info?.("[beeos-claw] Automation tools registered (create/create_webhook/capabilities/preflight/list/get/run/runs/get_run)")),o.canvasEnabled){sharedCanvasState||(sharedCanvasState=new CanvasStateManager);const t=sharedCanvasState;if(agentGateway&&agentKeys){t.setLogger(e.logger);const r=claimedSandboxId(),a=createSandboxCanvasTokenProvider(agentGateway,r,()=>sharedRuntimeAuthority?.authorityLease),n=n=>{const i=new CanvasRelayClient({canvasRelayUrl:o.canvasRelayUrl,agentKeys:agentKeys,...r?{}:{agentId:n.id},displayName:n.displayName,avatarUrl:n.avatarUrl,tokenProvider:a,onConnected:()=>p.flushPendingCanvasLinks(),onReconnect:()=>p.onRelayReconnected(),logger:e.logger});t.setRelayClient(i),t.setAgentId(n.id),p.wireRelayActionHandler(),i.connect(),e.logger.info?.(`[beeos-claw] Canvas Relay multiplexed client connected (agentId=${n.id}, name=${n.name??"none"})`)};e.registerService(createCanvasRelayService({getAgent:r?()=>({id:`sandbox:${r}`}):h,onceAgentReady:e=>sharedAgentMappings.onceReady(e),initRelay:n,stopRelay:()=>t.getRelayClient()?.disconnect(),logger:e.logger})),e.logger.info?.("[beeos-claw] Canvas Relay configured")}else e.logger.warn?.("[beeos-claw] Canvas Relay unavailable: agentGatewayUrl or agentKeys missing");const r={stateManager:t,logger:e.logger,writeObs:e=>a(e),getActiveSessionId:e=>p.getSessionIdForToolCall(e),getPlatformAgentId:e=>p.getPlatformAgentIdForToolCall(e),getGatewaySessionKey:e=>p.getGatewaySessionKeyForToolCall(e),waitForAgentSync:()=>sharedAgentMappings.waitForSynchronization(),publishStaticHtml:createStaticCanvasHtmlPublisher(pluginCloudRuntimeTarget(e)?o.agentGatewayUrl:void 0)},i=new FormSchemaRegistry,s=buildCronSchemas(n);i.register(s.create),i.register(s.update);const l=new ResourceDescriptorRegistry;l.register(CRON_RESOURCE);const c=e=>async(t,r,o)=>(p.preMapToolCallSession(t),e(t,r));e.registerTool({name:RENDER_UI_TOOL_NAME,description:RENDER_UI_TOOL_DESCRIPTION,parameters:RENDER_UI_TOOL_SCHEMA,execute:c(createRenderUiToolExecutor(r))}),e.registerTool({name:CLOSE_UI_TOOL_NAME,description:CLOSE_UI_TOOL_DESCRIPTION,parameters:CLOSE_UI_TOOL_SCHEMA,execute:c(createCloseUiHandler(r))}),p.setCanvasState(t,{schemaRegistry:i,descriptorRegistry:l});const u=p.getFormBuilder();u&&e.registerTool({name:RENDER_FORM_TOOL_NAME,description:buildRenderFormDescription(i),parameters:RENDER_FORM_TOOL_SCHEMA,execute:c(createRenderFormHandler({registry:i,builder:u,logger:e.logger}))});const d=p.getResourceRenderer();if(d){generateActionTools(l,e,async(e,t)=>p.gatewayRequest(e,t),d,e.logger)}const g=buildToolRoutingHint(BEEOS_FILE_RESOURCE_ROUTING_RULE,BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME),m=new Set([RENDER_UI_TOOL_NAME,CLOSE_UI_TOOL_NAME,RENDER_FORM_TOOL_NAME]),y=256,v=new Map;if("function"==typeof e.on){try{e.on("before_prompt_build",(e,t)=>{if(t?.sessionKey){if(v.size>=y&&!v.has(t.sessionKey)){const e=v.keys().next().value;void 0!==e&&v.delete(e)}v.set(t.sessionKey,t.channelId),rememberDeliveryWorkspace(t.sessionKey,t.workspaceDir)}const r=isThirdPartyChannel(n,{sessionKey:t?.sessionKey,channelId:t?.channelId});return t?.sessionKey||r?{appendSystemContext:buildAppendSystemContext({thirdParty:r,canvasSystemPrompt:`${CANVAS_PRESENTATION_GATE}\n\n${CANVAS_SYSTEM_PROMPT}`,toolRoutingHint:g})}:{appendSystemContext:g}}),e.logger.debug?.("[beeos-claw] Canvas system prompt hook registered: before_prompt_build")}catch{e.logger.debug?.("[beeos-claw] before_prompt_build hook not supported")}try{e.on("before_tool_call",(e,t)=>{if(t?.sessionKey&&p.setPendingToolCallSessionKey(t.sessionKey),!m.has(e.toolName))return;const r=t?.sessionKey?v.get(t.sessionKey):void 0,o=isThirdPartyChannel(n,{sessionKey:t?.sessionKey,channelId:r}),a=canvasToolBlockReason({thirdParty:o,hasSession:Boolean(t?.sessionKey)});return a?{block:!0,blockReason:a}:void 0}),e.logger.debug?.("[beeos-claw] Canvas tool guard registered: before_tool_call")}catch{e.logger.debug?.("[beeos-claw] before_tool_call hook not supported")}}e.logger.info?.("[beeos-claw] Canvas tools registered (render_ui, close_ui, render_form + auto-action tools)")}else e.logger.info?.("[beeos-claw] Canvas disabled by config (canvasEnabled=false)");if(o.bridge.shell.enabled&&!0===o.legacyTerminalWsEnabled){const t=createTerminalWebSocketService({config:{port:o.terminalWsPort,token:agentKeys?Buffer.from(agentKeys.publicKey).toString("base64"):"",allowedOrigins:o.terminalWsAllowedOrigins},terminalMgr:sharedTerminalManager,logger:e.logger,writeObs:a});e.registerService({id:"beeos-terminal-ws",start(){t.start(),e.logger.info?.(`[beeos-claw] Terminal WS started on port ${o.terminalWsPort}`)},stop(){t.stop(),e.logger.info?.("[beeos-claw] Terminal WS stopped")}})}else o.bridge.shell.enabled?e.logger.info?.("[beeos-claw] Legacy static-token Terminal WS disabled (default)"):e.logger.info?.("[beeos-claw] Terminal/shell disabled by config (bridge.shell.enabled=false)");if(t.openclawConfig){const r=mirrorOpenClawConfig(t.openclawConfig);r.copied?e.logger.info?.(`[beeos-claw] mirrored openclaw config to ${r.destinationPath}`):e.logger.debug?.(`[beeos-claw] openclaw config mirror skipped: ${r.reason}`)}}export function pluginCloudRuntimeTarget(e){const t=e.pluginConfig?.cloudRuntimeInstanceId;return cloudRuntimeTargetInstanceId("string"==typeof t?t:claimedSandboxId())}function attachNativeCloudChat(e,t){if(sharedNativeChatService)return e.registerService(sharedNativeChatService),sharedNativeCloudChat;const r=sharedRuntimeAuthority,o=t.messageBus.serviceUrl,a=sharedAcpServer,n=sharedSessionMutationCoordinator;if(!(r&&r.cloudTargetInstanceId&&o&&a&&n))return sharedNativeCloudChat;const i=sharedNativeCloudChat??createNativeCloudChatComposition({authority:nativeCloudChatAuthorityFromRuntimeAuthority(r),serviceUrl:o,logger:e.logger});if(sharedNativeCloudChat=i,!t.messageBus.enabled)return i;const s=i,l=r;let c;const u=new Map,d=new RuntimeAuthorityMessageBusLifecycle({authority:l,logger:e.logger,bus:{connect:async t=>{c?.(),u.clear(),c=s.adapter.listen({eventTypes:["message.created"]},r=>{if(r.type===APPROVAL_DECISION_MESSAGE_TYPE&&r.senderId?.startsWith("user:")&&isApprovalDocument(r.content))return void sharedApprovalBridge.onDecision(r.content);if("user.continue"===r.type&&isQuestionResponseDocument(r.content))return void sharedQuestionBridge.onResponse(r);const o=(r.content??{}).metadata??{},i="string"==typeof o.target_agent_id?o.target_agent_id:"",l=i?((t,r)=>{const o=sharedAgentMappings.snapshot();if(o)for(const[i,l]of o.entries()){if(l.id!==r)continue;if(l.instanceId!==t.instanceId)continue;const o=`${i}\0${l.id}`;let c=u.get(o);return c||(c={localAgentId:i,inbound:createImInboundHandler({runtime:e.runtime,pluginConfig:e.pluginConfig,client:s.adapter,localServer:{getLocalAgentId:()=>i,resolveLocalAgentId:e=>e===l.id?i:void 0,getDefaultPlatformAgent:()=>({instanceId:t.instanceId}),ensureImInboundSession:(e,t,r,o)=>{a.ensureImInboundSession(e,t,r,o)},chatAbort:(e,t)=>a.chatAbort(e,t)},promptRunStore:sharedPromptRunStore,waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{}),assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,approvalStreams:sharedApprovalBridge,questionStreams:sharedQuestionBridge,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:n,logger:e.logger,writeObs:sharedWriteObs,principalIdOverride:t.instanceId,activeRunAuthority:a.getActiveRunAuthority(),applyTurnModel:(e,t)=>a.applyImTurnModel(e,t),restoreTurnModel:e=>a.restoreImTurnModel(e),...agentGateway?{completeA2ATask:(t,r,o)=>completeA2ATask({gateway:agentGateway,logger:e.logger},t,r,o)}:{}})},u.set(o,c)),c}})(t,i):void 0;if(!l)return void e.logger.warn?.(`[beeos-claw] native cloud chat dropped unresolvable target_agent_id=${i||"missing"} message_id=${r.id}`);("chat_cancel"===r.type?l.inbound.onChatCancel(r):l.inbound.onChatMessage(r)).catch(t=>{e.logger.error?.(`[beeos-claw] native cloud chat dispatch failed message_id=${r.id}: ${t instanceof Error?t.message:String(t)}`)})});try{await s.adapter.connect()}catch(e){throw c?.(),c=void 0,e}},disconnect:async()=>{c?.(),c=void 0,u.clear(),await s.adapter.disconnect()}}});return sharedNativeChatService={id:"beeos-native-cloud-chat",async start(){d.start()},async stop(){await d.stop()}},e.registerService(sharedNativeChatService),e.logger.info?.("[beeos-claw] native Cloud personal-chat composition registered"),i}const plugin={id:"beeos-claw",name:"beeos-claw",description:"BeeOS platform bridge plugin for OpenClaw. Provides file upload/download, ACP bridge, and observability.",version:PLUGIN_VERSION,register(e){if(_initializing)return;registerCentralNativeContextEngine(e),registerSandboxNativeActivation(e,()=>{if(!sharedSessionMutationCoordinator)throw new Error("native session writer coordinator is unavailable");return sharedSessionMutationCoordinator.activeMutationCount},createSandboxNativeTargetLookup(()=>sharedRuntimeAuthority,()=>sharedGatewayClient,{logger:e.logger}),async()=>{const e=sharedGatewayClient;if(!e)throw new Error("OpenClaw gateway is not connected");await e.waitForConnected(3e4),await e.request("secrets.reload",{})});const t=pluginCloudRuntimeTarget(e),r=void 0!==t&&t!==sharedRuntimeAuthority?.cloudTargetInstanceId,o=planPluginRegistration(e.registrationMode,_fullRuntimeRegistered,r);if("skip"!==o){_initializing=!0;try{if(!hasRuntimeReplyApi(e.runtime))throw e.logger.error?.("[beeos-claw] FATAL: OpenClaw runtime.channel.reply.dispatchReplyFromConfig not exposed. Upgrade OpenClaw or revert beeos-claw."),new Error("openclaw_runtime_reply_api_unavailable");const t=(t,r)=>{registerUploadTools(e,t,r),registerArouterLatencyRouting(e),registerArouterMediaProviders(e)};if("capabilities"===o&&sharedPluginContext){if(cachedCapabilityTools.length>0){const t=resolveCapabilityToolReplay({currentRegisterTool:e.registerTool,wrappedRegisterTool:wrappedRegisterTool,originalRegisterTool:rawRegisterTool}),r=replayCachedPluginTools((r,o)=>t.call(e,r,o),cachedCapabilityTools);return registerArouterLatencyRouting(e),registerArouterMediaProviders(e),void e.logger.info?.(`[beeos-claw] capability re-register mode=${e.registrationMode} tools_only count=${r}`)}const r={current:sharedAcpServer??null};return t(sharedPluginContext,r),registerServices(e,sharedPluginContext,r),void e.logger.info?.(`[beeos-claw] capability re-register mode=${e.registrationMode} capabilities_only`)}const r=initializePlugin(e);if(!r)return;const a={current:null};installUnhandledRejectionObserver(e,r.writeObs,a),ensureRegisterToolCache(e),cacheRuntimeRegistrations(e),cachedCapabilityTools.length=0,t(r,a),agentGateway&&(e.on?e.on("before_agent_finalize",async(e,t)=>{if(await fileDeliveryFinalizeDecision(e),!e.runId||!t?.runId||e.runId===t.runId)return nativeHtmlDeliveryForRun(e.runId??t?.runId)?.beforeFinalize(e)}):e.logger.warn?.("[file-delivery] OpenClaw plugin hooks unavailable; finalization check disabled")),registerServices(e,r,a),sharedPluginContext=r,marksFullRuntimeRegistered(e.registrationMode,o)&&(_fullRuntimeRegistered=!0),_pluginRegisteredAt=Date.now(),e.logger.info?.("[beeos-claw] Plugin registered successfully")}finally{_initializing=!1}}else if(!e.registrationMode||"full"===e.registrationMode){const t=resolveCapabilityToolReplay({currentRegisterTool:e.registerTool,wrappedRegisterTool:wrappedRegisterTool,originalRegisterTool:rawRegisterTool});replayCachedPluginTools((r,o)=>t.call(e,r,o),cachedCapabilityTools),replayRuntimeRegistrations(e),registerArouterLatencyRouting(e),registerArouterMediaProviders(e)}}};export default plugin;
1
+ import{claimedSandboxId,identityLaneFromEnvironment}from"./runtime/identity-lane-lease.js";import{createCentralNativeComposition,requireCentralNativeSessionHost}from"./runtime/central-native-composition.js";import{createSandboxNativeTargetLookup,registerSandboxNativeActivation}from"./runtime/sandbox-native-activation.js";import{registerCentralNativeMemoryTools}from"./runtime/central-native-memory.js";import{harnessConnectorToolCaller}from"./connectors/harness-connector-mcp.js";import{registerCentralNativeContextEngine,centralNativeChatEnabled}from"./runtime/central-native-runtime.js";import{relayCentralAskUser}from"./runtime/central-native-interactions.js";import{consumeNativeOutputTool,nativeHtmlDeliveryForRun}from"./runtime/native-output-file-attempt.js";import{uploadNativeOutputFile}from"./upload/upload-file.js";import{nativeOutputToolCallGate}from"./upload/native-output-tool-hook.js";import{NativeInputFilesHttpClient}from"./runtime/native-input-files-http.js";import{fileDeliveryFinalizeDecision}from"./upload/finalize-hook.js";import{resolveConfigWithMeta,mirrorOpenClawConfig}from"./config.js";import{hasRuntimeReplyApi}from"./runtime/reply-router.js";import{PromptRunStore}from"./runtime/prompt-run-store.js";import{createMcpNativeProjectionNudge,fingerprintMcpServers}from"./acp-gateway/mcp-native-projection-nudge.js";import{createImHotPathDeferral}from"./runtime/im-hot-path-deferral.js";import{SessionWriteGate}from"./acp-gateway/session-write-gate.js";import{OpenClawSessionWriteQuiescence}from"./runtime/openclaw-session-write-quiescence.js";import{SessionMutationCoordinator}from"./runtime/session-mutation-coordinator.js";import{scheduleProcessRuntimeRestart}from"./runtime/runtime-restart-scheduler.js";import{createImInboundHandler}from"./im-inbound-handler.js";import{AgentGatewayClient,NodeRuntimeDeliveryPort,agentIdentityFromKeyPair,loadAgentKeyPair,signAgentMessage}from"@beeos-ai/cloud-harness-sdk";import{MessageServiceConversationRunBoundary}from"./runtime/message-service-conversation-run-boundary.js";import{AutomationTurnPolicy}from"./automation/turn-policy.js";import{registerAutomationTools}from"./automation/tools.js";import{extractBeeosConversationIdFromSessionKey}from"./runtime/openclaw-session-key-resolution.js";import{readOpenClawConfig}from"./runtime/openclaw-config.js";import{setOpenClawConfigSnapshot}from"./runtime/openclaw-session-model.js";import{BeeosClawMessageClientProcessOwner,createBeeosClawMessageTokenProvider}from"./message-client-composition.js";import{MessageProjectionInboundConsumer}from"./message-projection-inbound-consumer.js";import{MessageClientTerminalStateRecovery}from"./runtime/message-client-terminal-state-recovery.js";import{RuntimeAuthorityMessageBusLifecycle}from"./runtime/runtime-authority-message-bus-lifecycle.js";import{createNativeCloudChatComposition,nativeCloudChatAuthorityFromRuntimeAuthority}from"./runtime/native-cloud-chat-composition.js";import{MSConnectionStatusSnapshot}from"./runtime/ms-connection-status.js";import{FileInboundExecutionJournal}from"./inbound-execution-journal.js";import{completeA2ATask,registerA2ATools,TaskHandleRegistry}from"./a2a/tools.js";import{BEEOS_UPLOAD_TOOL_NAME,BEEOS_UPLOAD_TOOL_SCHEMA,BEEOS_UPLOAD_TOOL_DESCRIPTION,REQUEST_TIMEOUT_MS as BEEOS_UPLOAD_REQUEST_TIMEOUT_MS,executeUpload}from"./upload/tool.js";import{BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,BEEOS_DESKTOP_SCREENSHOT_TOOL_SCHEMA,BEEOS_DESKTOP_SCREENSHOT_TOOL_DESCRIPTION,executeDesktopScreenshot}from"./upload/desktop-screenshot-tool.js";import{BEEOS_LIST_FILES_TOOL_NAME,BEEOS_LIST_FILES_TOOL_SCHEMA,BEEOS_LIST_FILES_TOOL_DESCRIPTION,executeListFiles}from"./files/list-tool.js";import{BEEOS_FETCH_FILE_TOOL_NAME,BEEOS_FETCH_FILE_TOOL_SCHEMA,BEEOS_FETCH_FILE_TOOL_DESCRIPTION,executeFetchFile}from"./files/fetch-tool.js";import{writeUploadToolResult,cleanupUploadToolResultCache}from"./upload/result-cache.js";import{handleFileStage}from"./upload/file-stage.js";import{handleStatusRequest}from"./status.js";import{ACPServer}from"./acp-server.js";import{GatewayClient}from"./gateway-client.js";import{createObsEventWriter}from"./observability.js";import{resolvePluginVersion}from"./plugin-version.js";import{createTerminalWebSocketService}from"./terminal/websocket.js";import{TerminalManager}from"./terminal/session-manager.js";import{readDiscoveryCache,writeDiscoveryCache}from"./discovery-cache.js";import{setClaimedCloudRuntimeInstanceId,setUploadDeps}from"./upload/upload-file.js";import{registerLocalFileExtractor}from"./upload/local-file-extractors.js";import{browserScreenshotExtractor}from"./browser/screenshot-extractor.js";import{deliverableFileExtractor}from"./upload/deliverable-extractor.js";import{observeToolCallForDelivery,rememberDeliveryWorkspace}from"./upload/delivery-observe.js";import{sessionWorkspaceDir}from"./upload/delivery-ledger.js";import{BEEOS_FILE_RESOURCE_ROUTING_RULE}from"./files/beeos-file-uri.js";import{marksFullRuntimeRegistered,planPluginRegistration,replayCachedPluginTools,resolveCapabilityToolReplay}from"./plugin-registration-plan.js";import{buildAppendSystemContext,buildToolRoutingHint,canvasToolBlockReason}from"./prompt-system-context.js";import{CanvasStateManager}from"./canvas/state.js";import{createStaticCanvasHtmlPublisher}from"./canvas/static-html.js";import{CanvasRelayClient}from"./canvas/relay-client.js";import{createSandboxCanvasTokenProvider}from"./canvas/runtime-lease-token.js";import{createCanvasRelayService}from"./canvas/relay-service.js";import{RENDER_UI_TOOL_NAME,RENDER_UI_TOOL_DESCRIPTION,RENDER_UI_TOOL_SCHEMA,CLOSE_UI_TOOL_NAME,CLOSE_UI_TOOL_DESCRIPTION,CLOSE_UI_TOOL_SCHEMA,createRenderUiToolExecutor,createCloseUiHandler,CANVAS_PRESENTATION_GATE,CANVAS_SYSTEM_PROMPT}from"./canvas/tools.js";import{FormSchemaRegistry}from"./surface/form-schema-registry.js";import{buildCronSchemas}from"./surface/cron-schemas.js";import{RENDER_FORM_TOOL_NAME,RENDER_FORM_TOOL_SCHEMA,buildRenderFormDescription,createRenderFormHandler}from"./surface/render-form-tool.js";import{ResourceDescriptorRegistry}from"./surface/resource-descriptor-registry.js";import{CRON_RESOURCE}from"./surface/cron-resource.js";import{generateActionTools}from"./surface/action-tool-generator.js";import{buildThirdPartyChannelSet,isThirdPartyChannel}from"./channel-detection.js";import{registerArouterMediaProviders}from"./media/index.js";import{homedir}from"node:os";import{join}from"node:path";import{RuntimeProductionAuthority,cloudRuntimeTargetInstanceId}from"./runtime/runtime-production-authority.js";import{FileRuntimeCommandJournal}from"./runtime/runtime-command-journal.js";import{FileRuntimePoisonDeliveryJournal}from"./runtime/runtime-poison-delivery-journal.js";import{OpenClawNativeMcpProjection}from"./acp-gateway/openclaw-native-mcp-projection.js";import{LocalEncryptedCredentialReferenceVault}from"./acp-gateway/mcp-credential-reference-port.js";import{AgentGatewayGrantJwksReadinessAdapter,CloudRuntimeServiceTransportReadinessAdapter,RuntimeServiceTransportReadinessAdapter,createRuntimeServiceProductionCandidate}from"./runtime/runtime-service-production-candidate.js";import{fetchRuntimeLeaseAttempt}from"./runtime/message-service-runtime-authenticated-fetch.js";import{MessageServiceCronDeliveryHttpAuthority}from"./runtime/message-service-cron-delivery-http-authority.js";import{AgentMappingRegistry}from"./runtime/agent-mapping-registry.js";import{OpenClawRuntimeProcessOwner}from"./runtime/openclaw-runtime-process-owner.js";import{AgentGatewayHttpProjectionTransport,AgentGatewayTemplateOriginReporter,AgentProjectionProduction,OpenClawAgentProjectionSource}from"./runtime/agent-projection-production.js";import{MessageServiceRunOutputChannel}from"./runtime/message-service-run-output-channel.js";import{AssistantMessageCommitRouter}from"./runtime/assistant-message-commit-router.js";import{OpenClawApprovalBridge}from"./approval/bridge.js";import{APPROVAL_DECISION_MESSAGE_TYPE,isApprovalDocument}from"./approval/protocol.generated.js";import{isQuestionResponseDocument,OpenClawQuestionBridge}from"./question/bridge.js";import{ToolResultObservationRouter}from"./runtime/tool-result-observation-router.js";import{ModelCallObservationRouter,registerModelCallObservationHooks}from"./runtime/model-call-observability.js";import{registerArouterLatencyRouting}from"./runtime/arouter-latency-routing.js";import{createPeerRunOutputRouterFactory}from"./runtime/run-output-composition.js";const PLUGIN_VERSION=resolvePluginVersion();let agentKeys=null,agentGateway=null,sharedCanvasState=null,sharedAcpServer=null;const sharedSessionWriteGate=new SessionWriteGate,sharedPromptRunStore=new PromptRunStore,sharedAutomationTurnPolicy=new AutomationTurnPolicy;let lastOpenclawConfig;const sharedMcpNativeProjectionNudge=createMcpNativeProjectionNudge({getActiveImRunCount:()=>sharedPromptRunStore.size(),nudge:()=>{sharedAcpServer?.nudgeMcpNativeProjection()}}),sharedImHotPathDeferral=createImHotPathDeferral({getActiveImRunCount:()=>sharedPromptRunStore.size()});sharedPromptRunStore.setOnBecameIdle(()=>{sharedMcpNativeProjectionNudge.flushIfIdle({fingerprint:fingerprintMcpServers(lastOpenclawConfig)}),sharedImHotPathDeferral.notifyIdle()});const sharedAssistantMessageCommitRouter=new AssistantMessageCommitRouter,sharedToolResultObservationRouter=new ToolResultObservationRouter;let approvalLogger;const sharedApprovalBridge=new OpenClawApprovalBridge({request:(e,t)=>sharedGatewayClient?sharedGatewayClient.request(e,t):Promise.reject(new Error("Not connected to Gateway")),logger:{info:e=>approvalLogger?.info?.(e),warn:e=>approvalLogger?.warn?.(e)}}),sharedQuestionBridge=new OpenClawQuestionBridge({request:(e,t)=>sharedGatewayClient?sharedGatewayClient.request(e,t):Promise.reject(new Error("Not connected to Gateway")),logger:{info:e=>approvalLogger?.info?.(e),warn:e=>approvalLogger?.warn?.(e)}}),sharedModelCallObservationRouter=new ModelCallObservationRouter;let sharedSessionMutationCoordinator,sharedCentralPrompt,sharedRuntimeAuthority,sharedNativeChatService,sharedNativeCloudChat,sharedWriteObs=()=>{};const sharedMSConnectionStatus=new MSConnectionStatusSnapshot,sharedAgentMappings=new AgentMappingRegistry;let sharedGatewayClient,sharedRuntimeOwner,sharedAgentProjection,sharedRuntimeAgentCapabilities,sharedMcpProjection,sharedMcpCredentialVault;const sharedMessageClientOwner=new BeeosClawMessageClientProcessOwner;let sharedActiveMessageConsumer,sharedInboundExecutionJournal;const sharedTerminalManager=new TerminalManager;let _initializing=!1,_pluginRegisteredAt=0,_fullRuntimeRegistered=!1;const cachedCapabilityTools=[];let rawRegisterTool,wrappedRegisterTool;const cachedRuntimeServices=[],cachedRuntimeHooks=[];let rawRegisterService,wrappedRegisterService,rawOn,wrappedOn;function cacheRuntimeRegistrations(e){const t=e.registerService===wrappedRegisterService?rawRegisterService:e.registerService;if(rawRegisterService=t,wrappedRegisterService=r=>{cachedRuntimeServices.push(r),t.call(e,r)},e.registerService=wrappedRegisterService,cachedRuntimeServices.length=0,cachedRuntimeHooks.length=0,e.on){const t=e.on===wrappedOn?rawOn:e.on;rawOn=t,wrappedOn=(...r)=>{cachedRuntimeHooks.push(r),t.call(e,...r)},e.on=wrappedOn}}function replayRuntimeRegistrations(e){const t=e.registerService===wrappedRegisterService?rawRegisterService:e.registerService,r=e.on===wrappedOn?rawOn:e.on;for(const t of cachedRuntimeHooks)r.call(e,...t);for(const r of cachedRuntimeServices)t.call(e,r)}const ensureRegisterToolCache=e=>{const t=e.registerTool===wrappedRegisterTool?rawRegisterTool:e.registerTool;rawRegisterTool=t.bind(e),wrappedRegisterTool=(e,t)=>(cachedCapabilityTools.push({tool:e,options:t}),rawRegisterTool(e,t)),e.registerTool=wrappedRegisterTool};function agentKeyPairToIdentity(e){return{publicKeyBase64:()=>Buffer.from(e.publicKey).toString("base64"),sign:async t=>signAgentMessage(t,e.privateKey)}}let sharedPluginContext=null,unhandledRejectionObserverInstalled=!1;function installUnhandledRejectionObserver(e,t,r){unhandledRejectionObserverInstalled||(unhandledRejectionObserverInstalled=!0,process.on("unhandledRejection",r=>{const o=r instanceof Error?r.message:String(r),a=r instanceof Error?r.stack:void 0;e.logger.error?.(`[beeos-claw] unhandledRejection: ${o}${a?`\n${a}`:""}`),t({component:"plugin",domain:"fatal",name:"unhandled_rejection",severity:"error",summary:o,error:{code:"unhandled_rejection",message:o,...a?{stack:a}:{}}})}),process.on("uncaughtException",r=>{const o=r instanceof Error?r.message:String(r);e.logger.error?.(`[beeos-claw] uncaughtException: ${r instanceof Error?r.stack??r.message:String(r)}`),t({component:"plugin",domain:"fatal",name:"uncaught_exception",severity:"error",summary:o,error:{code:"uncaught_exception",message:o}})}))}function initializePlugin(e){let t,r;try{t=readOpenClawConfig(e.runtime,e.config)}catch{e.logger.error?.("[beeos-claw] OpenClaw runtime config could not be read; model dispatch will fail closed.")}try{r=resolveConfigWithMeta({pluginConfig:e.pluginConfig??{},openclawConfig:t})}catch(t){return e.logger.error?.(`[beeos-claw] Failed to resolve config: ${t instanceof Error?t.message:String(t)}`),null}const o=r.config,a=buildThirdPartyChannelSet(t);a.size>0&&e.logger.info?.(`[beeos-claw] Third-party channels detected: ${[...a].join(", ")}`);const n=o.log.enabled?createObsEventWriter({dir:o.log.dir,redaction:{gatewayToken:o.gateway.token},logger:e.logger}):()=>{};n({component:"plugin",domain:"lifecycle",name:"lifecycle.startup",severity:"info",payload:{pluginVersion:PLUGIN_VERSION,pid:process.pid,nodeVersion:process.version,cwd:process.cwd()}}),n({component:"plugin",domain:"config",name:"config.resolved",severity:"info",payload:{config:o,sources:r.sources,openclawConfigPath:r.openclawConfigPath}});for(const t of r.validation)n({component:"plugin",domain:"config",name:"config.validation",severity:t.severity,summary:t.message,error:{code:t.code,message:t.message,nextSteps:t.nextSteps}}),"error"===t.severity?e.logger.error?.(`[beeos-claw] ${t.message}`):e.logger.warn?.(`[beeos-claw] ${t.message}`);if(r.validation.some(e=>"error"===e.severity)&&e.logger.error?.("[beeos-claw] Plugin has configuration errors — some features may not work."),o.keyFile)try{agentKeys=loadAgentKeyPair(o.keyFile),agentGateway=o.agentGatewayUrl?new AgentGatewayClient({baseUrl:o.agentGatewayUrl,identity:agentIdentityFromKeyPair(agentKeys),onRetry:({method:t,path:r,attempt:o,delayMs:a,error:n})=>e.logger.warn?.(`[beeos-claw] Agent Gateway ${t} ${r} retry ${o} in ${a}ms: ${n instanceof Error?n.message:String(n)}`)}):null;const t=Buffer.from(agentKeys.publicKey).toString("base64");e.logger.info?.(`[beeos-claw] v${PLUGIN_VERSION} registering (publicKey: ${t})`)}catch(t){e.logger.warn?.(`[beeos-claw] Failed to load agent key pair: ${t}`),e.logger.info?.(`[beeos-claw] v${PLUGIN_VERSION} registering (no key pair — signed requests disabled)`)}else e.logger.info?.(`[beeos-claw] v${PLUGIN_VERSION} registering (no keyFile configured)`);return agentGateway&&(setUploadDeps({gateway:agentGateway,logger:e.logger}),registerLocalFileExtractor(browserScreenshotExtractor),registerLocalFileExtractor(deliverableFileExtractor),e.logger.info?.("[beeos-claw] Upload deps + local file extractors registered")),lastOpenclawConfig=t,sharedWriteObs=n,setOpenClawConfigSnapshot(()=>readOpenClawConfig(e.runtime,e.config)),{cfg:o,writeObs:n,thirdPartyChannels:a,openclawConfig:t}}function registerUploadTools(e,t,r){const{cfg:o,writeObs:a}=t,n=Boolean(pluginCloudRuntimeTarget(e));if(n){if(!e.on)throw new Error("native output Files Host hook unavailable");e.on("before_tool_call",(t,r)=>nativeOutputToolCallGate(t,r,e.logger))}cleanupUploadToolResultCache().catch(t=>{e.logger.warn?.(`[beeos_upload_file] cache cleanup failed on startup: ${String(t)}`)}),e.registerTool(t=>({name:BEEOS_UPLOAD_TOOL_NAME,description:BEEOS_UPLOAD_TOOL_DESCRIPTION,parameters:BEEOS_UPLOAD_TOOL_SCHEMA,async execute(r,i,s){const l=n?consumeNativeOutputTool(r):void 0,c=t.workspaceDir??sessionWorkspaceDir(t.sessionKey),u=await executeUpload(i,agentGateway,s,l?(e,t)=>uploadNativeOutputFile(e,o.agentGatewayUrl,l,t,s,BEEOS_UPLOAD_REQUEST_TIMEOUT_MS):void 0,e.logger,l?c:void 0);return e.logger.debug?.(`[beeos_upload_file] toolCallId=${r} ok=${u.ok}`),a({component:"upload-tool",domain:"tool",name:u.ok?"upload.success":"upload.failure",severity:u.ok?"info":"warn",payload:{toolCallId:r,ok:u.ok,fileCount:u.files?.length??0,error:u.error}}),(async t=>{try{await writeUploadToolResult(r,BEEOS_UPLOAD_TOOL_NAME,t),await cleanupUploadToolResultCache()}catch(t){e.logger.warn?.(`[beeos_upload_file] persist cache failed toolCallId=${r}: ${String(t)}`)}return t})(u)}}),{name:BEEOS_UPLOAD_TOOL_NAME}),e.registerTool({name:BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,description:BEEOS_DESKTOP_SCREENSHOT_TOOL_DESCRIPTION,parameters:BEEOS_DESKTOP_SCREENSHOT_TOOL_SCHEMA,async execute(t,r,o){e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${t} params=${JSON.stringify(r)}`);const n=await executeDesktopScreenshot(r,agentGateway,o);return e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${t} ok=${n.ok}`),a({component:"desktop-screenshot-tool",domain:"tool",name:n.ok?"desktop_screenshot.success":"desktop_screenshot.failure",severity:n.ok?"info":"warn",payload:{toolCallId:t,ok:n.ok,path:n.path,fileCount:n.files?.length??0,error:n.error}}),(async r=>{try{await writeUploadToolResult(t,BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,r),await cleanupUploadToolResultCache()}catch(r){e.logger.warn?.(`[beeos_desktop_screenshot] persist cache failed toolCallId=${t}: ${String(r)}`)}return r})(n)}}),e.registerHttpRoute({path:"/beeos/files/stage",auth:"gateway",async handler(e,r){await handleFileStage(e,r,t.cfg)}}),e.registerHttpRoute({path:"/beeos/status",auth:"plugin",handler(e,t){handleStatusRequest(e,t,{publicKey:agentKeys?.publicKey??null,pluginVersion:PLUGIN_VERSION})}}),e.registerTool({name:BEEOS_LIST_FILES_TOOL_NAME,description:BEEOS_LIST_FILES_TOOL_DESCRIPTION,parameters:BEEOS_LIST_FILES_TOOL_SCHEMA,async execute(t,r,o){e.logger.debug?.(`[beeos_list_files] toolCallId=${t} params=${JSON.stringify(r)}`);const n=await executeListFiles(r,agentGateway,o);return a({component:"file-list-tool",domain:"tool",name:n.ok?"list_files.success":"list_files.failure",severity:n.ok?"info":"warn",payload:{toolCallId:t,ok:n.ok,fileCount:n.files?.length??0,error:n.error}}),n}}),e.registerTool(t=>({name:BEEOS_FETCH_FILE_TOOL_NAME,description:BEEOS_FETCH_FILE_TOOL_DESCRIPTION,parameters:BEEOS_FETCH_FILE_TOOL_SCHEMA,async execute(r,i,s){e.logger.debug?.(`[beeos_fetch_file] toolCallId=${r} params=${JSON.stringify(i)}`);const l=await executeFetchFile(i,agentGateway,{signal:s,workspaceDir:t.workspaceDir,...n?{native:{gatewayUrl:o.agentGatewayUrl,capability:consumeNativeOutputTool(r)}}:{}});return a({component:"file-fetch-tool",domain:"tool",name:l.ok?"fetch_file.success":"fetch_file.failure",severity:l.ok?"info":"warn",payload:{toolCallId:r,ok:l.ok,path:l.path,size:l.size,error:l.error}}),l}}),{name:BEEOS_FETCH_FILE_TOOL_NAME})}function registerServices(e,t,r){const{cfg:o,writeObs:a,thirdPartyChannels:n}=t,i=centralNativeChatEnabled()?requireCentralNativeSessionHost(e.runtime):void 0;if(sharedAutomationTurnPolicy.disable(),"function"==typeof e.on)try{e.on("before_tool_call",(e,t)=>sharedAutomationTurnPolicy.check(e.toolName,{sessionKey:t?.sessionKey,runId:t?.runId??e.runId}),{priority:100}),sharedAutomationTurnPolicy.enable()}catch{e.logger.warn?.("[beeos-claw] Automation Wake disabled: tool guard unavailable")}if("function"!=typeof e.on){if(o.messageBus.enabled)throw new Error("openclaw_before_message_write_hook_unavailable")}else registerModelCallObservationHooks((t,r)=>e.on(t,r),sharedModelCallObservationRouter),e.on("before_message_write",(t,r)=>{const o=t.sessionKey??r.sessionKey;if(!o)return void e.logger.debug?.("[before_message_write] ignored assistant write without sessionKey");sharedAssistantMessageCommitRouter.route(o,t.message)||e.logger.debug?.(`[before_message_write] no active IM commit target sessionKey=${o} active_targets=${sharedAssistantMessageCommitRouter.size()}`)}),e.on("before_tool_call",(e,t)=>{if("ask_user"!==(e.toolName||t.toolName))return;const r={sessionKey:t.sessionKey,runId:t.runId??e.runId,toolCallId:t.toolCallId??e.toolCallId};sharedQuestionBridge.observeAskUser(r),relayCentralAskUser((e,t)=>sharedGatewayClient?sharedGatewayClient.request(e,t):Promise.reject(new Error("Not connected to Gateway")),r).catch(e=>approvalLogger?.warn?.(`[question] central relay failed: ${e instanceof Error?e.message:String(e)}`))}),e.on("after_tool_call",(t,r)=>{const o=r.sessionKey,a=t.toolCallId??r.toolCallId,n=t.toolName||r.toolName;if(t.runId&&r.runId&&t.runId!==r.runId||t.toolCallId&&r.toolCallId&&t.toolCallId!==r.toolCallId||nativeHtmlDeliveryForRun(t.runId??r.runId)?.observe(n,t.params,t.result,Boolean(t.error),a),!o||!a||!n)return void e.logger.debug?.(`[after_tool_call] ignored structured result without correlation sessionKey=${o??"missing"} toolCallId=${a??"missing"}`);observeToolCallForDelivery(t,o);sharedToolResultObservationRouter.route(o,{toolCallId:a,toolName:n,rawResult:t.result,isError:Boolean(t.error)})||e.logger.debug?.(`[after_tool_call] no active IM observation target sessionKey=${o} active_targets=${sharedToolResultObservationRouter.size()}`)});const s=agentKeys?Buffer.from(agentKeys.publicKey).toString("base64"):void 0,l=join(process.env.OPENCLAW_HOME||join(homedir(),".openclaw"),"beeos"),c=sharedInboundExecutionJournal??=new FileInboundExecutionJournal(join(l,"inbound-execution-journal.v1.jsonl"));sharedMcpProjection??=new OpenClawNativeMcpProjection,!sharedMcpCredentialVault&&agentKeys&&s&&(sharedMcpCredentialVault=new LocalEncryptedCredentialReferenceVault(join(l,"mcp-credential-vault.json"),s,agentKeys.privateKey));const u=pluginCloudRuntimeTarget(e);if(setClaimedCloudRuntimeInstanceId(u),u&&(!agentKeys||!agentGateway))throw new Error("Cloud runtime authority requires an agent identity and gateway transport");const d=sharedRuntimeAuthority?.cloudTargetInstanceId;if(d&&u&&d!==u)throw new Error("Cloud runtime authority target changed during process lifetime");if(sharedRuntimeAuthority&&!d&&u&&sharedRuntimeAuthority.bindCloudTarget(u),!sharedRuntimeAuthority&&agentKeys&&agentGateway&&(sharedRuntimeAuthority=new RuntimeProductionAuthority({stateDirectory:l,gateway:agentGateway,keys:agentKeys,targetInstanceId:u,logger:e.logger,getMSConnectionStatus:e=>sharedMSConnectionStatus.get(e),identityLane:identityLaneFromEnvironment()})),sharedGatewayClient||(sharedGatewayClient=new GatewayClient({url:o.gateway.url,token:o.gateway.token||"",clientId:o.gateway.clientId,openclawCanvasCompat:!!o.openclawCanvasCompat,retry:{baseMs:o.retry.baseMs,maxMs:o.retry.maxMs,maxAttempts:o.retry.maxAttempts}}),sharedGatewayClient.on("gateway-event",(e,t)=>{sharedApprovalBridge.onGatewayEvent(e,t),sharedQuestionBridge.onGatewayEvent(e,t)})),approvalLogger??=e.logger,sharedRuntimeAgentCapabilities??={canvas:o.canvasEnabled,terminal:!1,webSsh:!1,fileSystem:!0,image:!0,audio:!1,mcp:!0,cron:!0,streaming:!0,pushNotifications:o.messageBus.enabled,...o.messageBus.enabled&&sharedAutomationTurnPolicy.isReady()&&agentGateway?{automationWake:!0}:{}},!sharedAgentProjection&&sharedRuntimeAuthority&&agentGateway){const t=sharedRuntimeAuthority;sharedAgentProjection=new AgentProjectionProduction({authority:t,stateFile:join(t.stateDirectory,"runtime-agent-projection.json"),journal:t.journal,identities:t.identities,source:new OpenClawAgentProjectionSource(()=>sharedGatewayClient),transport:new AgentGatewayHttpProjectionTransport({gateway:agentGateway,getRuntimeLeaseCredential:e=>{const r=t.authorityLease;if(!r||r.instanceId!==e.instanceId||r.leaseId!==e.leaseId||r.runtimeEpoch!==e.runtimeEpoch||r.handlerIdentity!==e.handlerIdentity)throw new Error("agent projection fenced by current runtime lease");return r.runtimeLeaseCredential},onAccepted:t=>{0!==t.size&&sharedAgentMappings.replace(t).catch(t=>{e.logger.warn?.("[agent-projection] mapping publication failed: "+(t instanceof Error?t.message:String(t)))})}}),capabilities:sharedRuntimeAgentCapabilities,logger:e.logger})}sharedRuntimeOwner??=new OpenClawRuntimeProcessOwner(sharedGatewayClient,sharedAgentProjection,e.logger);const g=sharedRuntimeOwner;sharedSessionMutationCoordinator??=new SessionMutationCoordinator(sharedSessionWriteGate,new OpenClawSessionWriteQuiescence(e.logger,{agentId:o.gateway.agentId||"main",...i?{nativeWritersQuiescent:e=>i.nativeWritersQuiescent({sessionKey:e})}:{}}),e.logger,{onRecoveryRequired:t=>{scheduleProcessRuntimeRestart(t,e.logger)}});const m=sharedSessionMutationCoordinator;if(i&&!sharedCentralPrompt){if(!sharedRuntimeAuthority?.cloudTargetInstanceId)throw new Error("central native chat requires the provisioned Cloud runtime authority");sharedCentralPrompt=createCentralNativeComposition({runtime:e.runtime,host:i,gatewayOrigin:o.agentGatewayUrl,stateDirectory:l,authority:sharedRuntimeAuthority,coordinator:m,logger:e.logger})}if(i&&registerCentralNativeMemoryTools(e),!sharedAcpServer){const t=sharedRuntimeAuthority&&agentGateway?new AgentGatewayTemplateOriginReporter({gateway:agentGateway}):void 0;sharedAcpServer=new ACPServer(o,e.logger,m,a,agentGateway??void 0,s,n,sharedTerminalManager,sharedRuntimeAuthority,void 0,sharedMcpProjection,sharedMcpCredentialVault,{gateway:g.client,agentProjection:sharedAgentProjection,markAgentProjectionDirty:()=>sharedAgentProjection?.markDirty(),templateOriginReporter:t,agentMappings:sharedAgentMappings,agentCapabilities:sharedRuntimeAgentCapabilities,createRunOutputRouter:createPeerRunOutputRouterFactory(new MessageServiceRunOutputChannel({getClient:()=>sharedMessageClientOwner.current?.client??null,logger:e.logger,writeObs:a})),runExclusive:(t,r,o)=>sharedImHotPathDeferral.runExclusive(t,r,e.logger,o)})}const p=sharedAcpServer,h=()=>sharedAgentMappings.snapshot()?.values().next().value;r.current=p,sharedMcpNativeProjectionNudge.request({registrationMode:e.registrationMode,fingerprint:fingerprintMcpServers(t.openclawConfig),logger:e.logger});const y=sharedPromptRunStore,{enabled:v,principalId:w,a2aEnabled:f}=o.messageBus;let C;!u&&o.agentGatewayUrl&&agentKeys&&(C=createBeeosClawMessageTokenProvider({agentGatewayUrl:o.agentGatewayUrl,identity:agentKeyPairToIdentity(agentKeys)}));const R=process.env.MESSAGE_RUNTIME_DELIVERY_KEY?.trim(),b=w||process.env.BEEOS_PRINCIPAL_ID||"",S=C?sharedMessageClientOwner.configure({tokenProvider:C,identityId:b,...o.messageBus.serviceUrl?{serviceUrl:o.messageBus.serviceUrl}:{},logger:e.logger,...sharedRuntimeAuthority&&R?{runtimeDelivery:{scopedDeliveryKey:R,authority:{currentLease:()=>{const e=sharedRuntimeAuthority?.authorityLease,t=sharedRuntimeAuthority?.currentConsumerBinding();return e&&t?{...e,journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}:null}}}}:{}}):void 0,E=u&&o.messageBus.serviceUrl&&sharedRuntimeAuthority?new NodeRuntimeDeliveryPort({serviceOrigin:async()=>o.messageBus.serviceUrl},{currentLease:()=>{const e=sharedRuntimeAuthority?.authorityLease,t=sharedRuntimeAuthority?.currentConsumerBinding();return e&&t&&e.instanceId===u?{...e,journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}:null},subscribeAuthority:e=>sharedRuntimeAuthority.subscribeAuthority(e)}):void 0;attachNativeCloudChat(e,o);const O=sharedRuntimeAuthority,_=o.messageBus.serviceUrl;S&&O&&_&&R?p.setCronConversationDelivery({deliver:async e=>{const t=O.authorityLease;if(!t)throw new Error("current runtime authority lease unavailable for cron delivery");const r=new MessageServiceCronDeliveryHttpAuthority({messageServiceUrl:_,scopedDeliveryKey:R,fetchAuthorized:(e,t)=>fetchRuntimeLeaseAttempt(e,t??{})});return await r.deliver({...e,runtimeLeaseCredential:t.runtimeLeaseCredential})}}):p.setCronConversationDelivery(void 0);const A=sharedRuntimeAuthority?.journal??new FileRuntimeCommandJournal(join(l,"runtime-command-journal.json"),void 0,void 0,{onMaintenanceError:t=>e.logger.error?.(`[runtime-journal] event=checkpoint_failed trigger=threshold error=${t instanceof Error?t.message:String(t)}`)}),I=g.createRegistrationToken();e.registerService({id:"beeos-acp",async start(){const t=Date.now(),r=_pluginRegisteredAt?t-_pluginRegisteredAt:-1;e.logger.info?.(`[beeos-claw] beeos-acp service start() begin, sincePluginRegister=${r}ms, bridge.url=${o.bridge.url||"(empty)"}`);const a=await createRuntimeServiceProductionCandidate({...agentGateway?{authorizationAdapter:new AgentGatewayGrantJwksReadinessAdapter({gateway:agentGateway})}:{},onGrantJwksWarm:t=>{t.ready?e.logger.info?.("[beeos-claw] Gateway grant keyset loaded"):e.logger.warn?.(`[beeos-claw] Gateway grant keyset not ready yet (attempt ${t.attempt}): ${t.error instanceof Error?t.error.message:String(t.error)}`)},...S&&agentGateway&&R?{transportAdapter:new RuntimeServiceTransportReadinessAdapter({gateway:agentGateway,messageService:S.nodeTransport,messageClient:S.client,configuredServiceUrl:o.messageBus.serviceUrl,scopedDeliveryKey:R})}:{},...E&&agentGateway&&o.messageBus.serviceUrl?{cloudTransportAdapter:new CloudRuntimeServiceTransportReadinessAdapter({gateway:agentGateway,configuredServiceUrl:o.messageBus.serviceUrl,runtimeDelivery:E,...sharedCentralPrompt?{centralPrompt:sharedCentralPrompt}:{},...sharedNativeCloudChat?{sessionNewConversation:sharedNativeCloudChat.sessionNewConversation,nativePrompt:{http:sharedNativeCloudChat.http,inputFiles:new NativeInputFilesHttpClient(o.agentGatewayUrl,()=>sharedRuntimeAuthority.authorityLease,(e,t)=>fetch(e,t)),runBoundary:new MessageServiceConversationRunBoundary({transport:{start:e=>E.startConversationRun(e),finish:e=>E.finishConversationRun(e)}}),host:{htmlDeliveryEnabled:o.canvasEnabled,resolveNativePromptSessionKey:(e,t)=>p.resolveNativePromptSessionKey(e,t),prepareNativePromptModel:(e,t,r)=>p.prepareNativePromptModel(e,t,r),runtime:e.runtime,pluginConfig:o,logger:e.logger,promptRunStore:y,assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,approvalStreams:sharedApprovalBridge,questionStreams:sharedQuestionBridge,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:m,abortTransport:{chatAbort:(e,t)=>p.chatAbort(e,t)},activeRunAuthority:p.getActiveRunAuthority(),waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{})}}}:{}})}:{},commandJournal:A,poisonJournal:new FileRuntimePoisonDeliveryJournal(join(l,"runtime-poison-deliveries.json")),onConsumerDeliveryError:t=>{const r=null!==t&&"object"==typeof t?t:{},o=e=>"string"==typeof e&&e.length>0&&e.length<=256&&!/[\u0000-\u001f\u007f]/.test(e)?JSON.stringify(e):JSON.stringify("unavailable"),a="string"==typeof r.code&&/^[A-Za-z0-9_.:-]{1,64}$/.test(r.code)?r.code:"unavailable",n="number"==typeof r.status&&Number.isInteger(r.status)&&r.status>=100&&r.status<=599?String(r.status):"unavailable";e.logger.error?.(`[runtime-service] delivery worker failed before acknowledgement; delivery retained for retry: operation_id=${o(r.operationId)} delivery_id=${o(r.deliveryId)} code=${a} status=${n}`)},onConsumerLeaseStarvation:({starvedForMs:t,recovered:r})=>{const o=Math.round(t/1e3);r?e.logger.info?.(`[runtime-service] runtime authority lease restored after ${o}s without delivery reads`):e.logger.warn?.(`[runtime-service] no runtime authority lease for ${o}s; delivery reads suspended, queued runtime operations (model switch, session control) will not be consumed`)},onConsumerRequestFailure:t=>e.logger.error?.(`[runtime-service] request failed operationId=${t.operationId} method=${t.method}: ${t.error instanceof Error?t.error.stack??t.error.message:String(t.error)}`)});if(sharedRuntimeAuthority?.setRuntimeServiceMethods("ready"===a.status?a.serviceMethods:[]),sharedRuntimeAuthority?.setRuntimeResourceBindingContractRevision("ready"===a.status?a.resourceBindingContractRevision:void 0),p.setRuntimeRpcConsumerFactory("ready"===a.status?a.factory:void 0),"unavailable"===a.status?e.logger.warn?.("[runtime-service] capability fenced: "+a.blockers.map(e=>e.id).join(",")):a.capabilityBlockers.length&&e.logger.warn?.("[runtime-service] method capability fenced: "+a.capabilityBlockers.map(e=>e.method).join(",")),!o.bridge.url&&agentGateway){const t=Date.now(),r=await agentGateway.bridge.config();if(e.logger.info?.(`[beeos-claw] bridge discovery took ${Date.now()-t}ms result=${r?.url??"null"}`),r)o.bridge.url=r.url,writeDiscoveryCache({bridge:{url:r.url,discoveredAt:Date.now()}}),e.logger.info?.(`[beeos-claw] Bridge URL discovered from Agent Gateway: ${r.url}`);else{const t=readDiscoveryCache();t?.bridge?.url?(o.bridge.url=t.bridge.url,e.logger.info?.(`[beeos-claw] Bridge URL from cache (GW unreachable): ${t.bridge.url}`)):e.logger.debug?.("[beeos-claw] Bridge URL not available (no GW, no cache) — bridge disabled")}}await g.acquire(I);try{await p.start(o.bridge.url||void 0)}catch(e){throw await g.release(I),e}e.logger.info?.(`[beeos-claw] ACP Server started (total service start: ${Date.now()-t}ms)`)},async stop(){try{await g.release(I)}finally{await p.stop()}await A.checkpoint(),e.logger.info?.("[runtime-service] command journal checkpoint completed"),e.logger.info?.("[beeos-claw] ACP Server stopped")}});if(v&&void 0!==C&&C){const t=sharedMessageClientOwner.createRegistrationToken(),r=async(e,t)=>{const r=await C(e);if(!r.identityId||r.identityId!==e)throw new Error("Message SDK token identity did not match the current runtime authority");return{principalId:e,runtimeEpoch:t}},o=(e,t,r)=>({getLocalAgentId:()=>t,resolveLocalAgentId:e=>e===r?t:void 0,getDefaultPlatformAgent:()=>({instanceId:e.principalId}),ensureImInboundSession:(e,t,r,o)=>{p.ensureImInboundSession(e,t,r,o)},chatAbort:(e,t)=>p.chatAbort(e,t)}),n=sharedRuntimeAuthority?new RuntimeAuthorityMessageBusLifecycle({authority:sharedRuntimeAuthority,logger:e.logger,bus:{connect:async n=>{await sharedMessageClientOwner.acquire(t,async t=>{const i=await r(n.instanceId,n.runtimeEpoch),s=t.client,l={leaseId:n.leaseId,runtimeEpoch:n.runtimeEpoch};sharedMSConnectionStatus.bind(l);const u=new Map,d=new MessageProjectionInboundConsumer({client:s,bindings:()=>{const t=sharedRuntimeAuthority?.authorityLease;if(!t||t.instanceId!==i.principalId||t.runtimeEpoch!==i.runtimeEpoch)return[];const r=sharedAgentMappings.snapshot();return r?[...r.entries()].flatMap(([r,n])=>{if(!n.id||n.instanceId!==i.principalId)return[];let l=u.get(n.id);return l&&l.localAgentId===r||(l={localAgentId:r,inbound:createImInboundHandler({automationTurnPolicy:sharedAutomationTurnPolicy,runtime:e.runtime,pluginConfig:e.pluginConfig,client:s,localServer:o(i,r,n.id),promptRunStore:y,waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{}),assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,approvalStreams:sharedApprovalBridge,questionStreams:sharedQuestionBridge,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:m,logger:e.logger,writeObs:a,principalIdOverride:i.principalId,activeRunAuthority:p.getActiveRunAuthority(),applyTurnModel:(e,t)=>p.applyImTurnModel(e,t),restoreTurnModel:e=>p.restoreImTurnModel(e),...agentGateway?{completeA2ATask:(t,r,o)=>completeA2ATask({gateway:agentGateway,logger:e.logger},t,r,o)}:{}})},u.set(n.id,l)),[{principalId:i.principalId,targetAgentId:n.id,runtimeEpoch:t.runtimeEpoch,inbound:l.inbound}]}):[]},executionJournal:c,logger:e.logger}),g=sharedAgentMappings.subscribe(()=>{sharedActiveMessageConsumer===d&&d.refresh()}),h=sharedRuntimeAuthority?.subscribeAuthority(()=>{sharedActiveMessageConsumer===d&&d.refresh()})??(()=>{}),v=new MessageClientTerminalStateRecovery({logger:e.logger,isCurrent:()=>{if(sharedActiveMessageConsumer!==d)return!1;const e=sharedRuntimeAuthority?.authorityLease;return null!=e&&e.instanceId===i.principalId&&e.runtimeEpoch===i.runtimeEpoch&&e.leaseId===n.leaseId&&e.handlerIdentity===n.handlerIdentity},reconnect:async()=>{if("failed"===s.getSnapshot().connection){await s.connect();try{await p.rebindRuntimeDelivery()}catch(t){e.logger.warn?.(`[beeos-claw] runtime Service delivery rebind failed after MessageClient recovery: ${t instanceof Error?t.message:String(t)}`)}}}});let w=s.getSnapshot().connection;sharedMSConnectionStatus.setIfCurrent(l,w);const f=s.subscribe(()=>{const t=s.getSnapshot();t.connection!==w&&(w=t.connection,sharedMSConnectionStatus.setIfCurrent(l,t.connection),"connected"===t.connection?(v.notifyConnected(),e.logger.info?.(`[beeos-claw] connection transport=message_service_realtime state=connected localAgentId=${p.getLocalAgentId()} principalId=${i.principalId}`)):"failed"===t.connection?(e.logger.warn?.(`[beeos-claw] connection transport=message_service_realtime state=failed principalId=${i.principalId} recoveryError=${t.recoveryError??"unknown"}`),v.notifyFailed()):"disconnected"!==t.connection&&"reconnecting"!==t.connection||e.logger.warn?.(`[beeos-claw] connection transport=message_service_realtime state=${t.connection} principalId=${i.principalId}; SDK owns reconnect/recovery`))});sharedActiveMessageConsumer=d,d.start();try{await s.connect()}catch(e){throw sharedActiveMessageConsumer===d&&(sharedActiveMessageConsumer=void 0),sharedMSConnectionStatus.resetIfCurrent(l),v.dispose(),await d.stop(),g(),h(),f(),await s.disconnect().catch(()=>{}),e}try{await p.rebindRuntimeDelivery()}catch(t){e.logger.warn?.(`[beeos-claw] runtime Service delivery rebind failed after MessageClient connect: ${t instanceof Error?t.message:String(t)}`)}return async()=>{sharedActiveMessageConsumer===d&&(sharedActiveMessageConsumer=void 0),sharedMSConnectionStatus.resetIfCurrent(l),v.dispose(),await d.stop(),h(),f(),await s.disconnect(),e.logger.info?.("[beeos-claw] MessageClient disconnected")}})},disconnect:async()=>{await sharedMessageClientOwner.release(t)}}}):void 0;e.registerService({id:"beeos-message-bus",async start(){n?n.start():e.logger.warn?.("[beeos-claw] Message bus requires runtime authority; waiting is unavailable without Agent Gateway runtime identity")},async stop(){await(n?.stop())}})}else v?e.logger.warn?.("[beeos-claw] Message bus enabled but Agent Gateway token provider is unavailable — disabled"):e.logger.info?.(`[beeos-claw] Message bus disabled (enabled=${v})`);if(o.messageBus.enabled&&u&&!sharedNativeCloudChat&&e.logger.warn?.("[beeos-claw] Cloud message bus enabled but native composition unavailable (messageBus.serviceUrl or runtime authority missing) — disabled"),!1!==f&&agentGateway){const t=e=>p.getGatewaySessionKeyForToolCall(e),r=e=>p.getMentionsForToolCall(e),o=(e,t)=>{p.broadcastNotification(e,t)},a=new TaskHandleRegistry;registerA2ATools(e,{gateway:agentGateway,logger:e.logger},a,t,r,o,()=>h()?.instanceId),e.logger.info?.("[beeos-claw] A2A tools registered (beeos_discover_agents, beeos_call_agent) via REST")}if(agentGateway&&(registerAutomationTools(e,{gateway:agentGateway,callConnectorTool:harnessConnectorToolCaller(),logger:e.logger,getDefaultAgent:()=>{const e=h();return e?{id:e.id,instanceId:e.instanceId}:void 0},getCurrentConversationId:e=>{const t=p.getGatewaySessionKeyForToolCall(e);return t?extractBeeosConversationIdFromSessionKey(t):void 0}}),e.logger.info?.("[beeos-claw] Automation tools registered (create/create_webhook/capabilities/preflight/list/get/run/runs/get_run)")),o.canvasEnabled){sharedCanvasState||(sharedCanvasState=new CanvasStateManager);const t=sharedCanvasState;if(agentGateway&&agentKeys){t.setLogger(e.logger);const r=claimedSandboxId(),a=createSandboxCanvasTokenProvider(agentGateway,r,()=>sharedRuntimeAuthority?.authorityLease),n=n=>{const i=new CanvasRelayClient({canvasRelayUrl:o.canvasRelayUrl,agentKeys:agentKeys,...r?{}:{agentId:n.id},displayName:n.displayName,avatarUrl:n.avatarUrl,tokenProvider:a,onConnected:()=>p.flushPendingCanvasLinks(),onReconnect:()=>p.onRelayReconnected(),logger:e.logger});t.setRelayClient(i),t.setAgentId(n.id),p.wireRelayActionHandler(),i.connect(),e.logger.info?.(`[beeos-claw] Canvas Relay multiplexed client connected (agentId=${n.id}, name=${n.name??"none"})`)};e.registerService(createCanvasRelayService({getAgent:r?()=>({id:`sandbox:${r}`}):h,onceAgentReady:e=>sharedAgentMappings.onceReady(e),initRelay:n,stopRelay:()=>t.getRelayClient()?.disconnect(),logger:e.logger})),e.logger.info?.("[beeos-claw] Canvas Relay configured")}else e.logger.warn?.("[beeos-claw] Canvas Relay unavailable: agentGatewayUrl or agentKeys missing");const r={stateManager:t,logger:e.logger,writeObs:e=>a(e),getActiveSessionId:e=>p.getSessionIdForToolCall(e),getPlatformAgentId:e=>p.getPlatformAgentIdForToolCall(e),getGatewaySessionKey:e=>p.getGatewaySessionKeyForToolCall(e),waitForAgentSync:()=>sharedAgentMappings.waitForSynchronization(),publishStaticHtml:createStaticCanvasHtmlPublisher(pluginCloudRuntimeTarget(e)?o.agentGatewayUrl:void 0)},i=new FormSchemaRegistry,s=buildCronSchemas(n);i.register(s.create),i.register(s.update);const l=new ResourceDescriptorRegistry;l.register(CRON_RESOURCE);const c=e=>async(t,r,o)=>(p.preMapToolCallSession(t),e(t,r));e.registerTool({name:RENDER_UI_TOOL_NAME,description:RENDER_UI_TOOL_DESCRIPTION,parameters:RENDER_UI_TOOL_SCHEMA,execute:c(createRenderUiToolExecutor(r))}),e.registerTool({name:CLOSE_UI_TOOL_NAME,description:CLOSE_UI_TOOL_DESCRIPTION,parameters:CLOSE_UI_TOOL_SCHEMA,execute:c(createCloseUiHandler(r))}),p.setCanvasState(t,{schemaRegistry:i,descriptorRegistry:l});const u=p.getFormBuilder();u&&e.registerTool({name:RENDER_FORM_TOOL_NAME,description:buildRenderFormDescription(i),parameters:RENDER_FORM_TOOL_SCHEMA,execute:c(createRenderFormHandler({registry:i,builder:u,logger:e.logger}))});const d=p.getResourceRenderer();if(d){generateActionTools(l,e,async(e,t)=>p.gatewayRequest(e,t),d,e.logger)}const g=buildToolRoutingHint(BEEOS_FILE_RESOURCE_ROUTING_RULE,BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME),m=new Set([RENDER_UI_TOOL_NAME,CLOSE_UI_TOOL_NAME,RENDER_FORM_TOOL_NAME]),y=256,v=new Map;if("function"==typeof e.on){try{e.on("before_prompt_build",(e,t)=>{if(t?.sessionKey){if(v.size>=y&&!v.has(t.sessionKey)){const e=v.keys().next().value;void 0!==e&&v.delete(e)}v.set(t.sessionKey,t.channelId),rememberDeliveryWorkspace(t.sessionKey,t.workspaceDir)}const r=isThirdPartyChannel(n,{sessionKey:t?.sessionKey,channelId:t?.channelId});return t?.sessionKey||r?{appendSystemContext:buildAppendSystemContext({thirdParty:r,canvasSystemPrompt:`${CANVAS_PRESENTATION_GATE}\n\n${CANVAS_SYSTEM_PROMPT}`,toolRoutingHint:g})}:{appendSystemContext:g}}),e.logger.debug?.("[beeos-claw] Canvas system prompt hook registered: before_prompt_build")}catch{e.logger.debug?.("[beeos-claw] before_prompt_build hook not supported")}try{e.on("before_tool_call",(e,t)=>{if(t?.sessionKey&&p.setPendingToolCallSessionKey(t.sessionKey),!m.has(e.toolName))return;const r=t?.sessionKey?v.get(t.sessionKey):void 0,o=isThirdPartyChannel(n,{sessionKey:t?.sessionKey,channelId:r}),a=canvasToolBlockReason({thirdParty:o,hasSession:Boolean(t?.sessionKey)});return a?{block:!0,blockReason:a}:void 0}),e.logger.debug?.("[beeos-claw] Canvas tool guard registered: before_tool_call")}catch{e.logger.debug?.("[beeos-claw] before_tool_call hook not supported")}}e.logger.info?.("[beeos-claw] Canvas tools registered (render_ui, close_ui, render_form + auto-action tools)")}else e.logger.info?.("[beeos-claw] Canvas disabled by config (canvasEnabled=false)");if(o.bridge.shell.enabled&&!0===o.legacyTerminalWsEnabled){const t=createTerminalWebSocketService({config:{port:o.terminalWsPort,token:agentKeys?Buffer.from(agentKeys.publicKey).toString("base64"):"",allowedOrigins:o.terminalWsAllowedOrigins},terminalMgr:sharedTerminalManager,logger:e.logger,writeObs:a});e.registerService({id:"beeos-terminal-ws",start(){t.start(),e.logger.info?.(`[beeos-claw] Terminal WS started on port ${o.terminalWsPort}`)},stop(){t.stop(),e.logger.info?.("[beeos-claw] Terminal WS stopped")}})}else o.bridge.shell.enabled?e.logger.info?.("[beeos-claw] Legacy static-token Terminal WS disabled (default)"):e.logger.info?.("[beeos-claw] Terminal/shell disabled by config (bridge.shell.enabled=false)");if(t.openclawConfig){const r=mirrorOpenClawConfig(t.openclawConfig);r.copied?e.logger.info?.(`[beeos-claw] mirrored openclaw config to ${r.destinationPath}`):e.logger.debug?.(`[beeos-claw] openclaw config mirror skipped: ${r.reason}`)}}export function pluginCloudRuntimeTarget(e){const t=e.pluginConfig?.cloudRuntimeInstanceId;return cloudRuntimeTargetInstanceId("string"==typeof t?t:claimedSandboxId())}function attachNativeCloudChat(e,t){if(sharedNativeChatService)return e.registerService(sharedNativeChatService),sharedNativeCloudChat;const r=sharedRuntimeAuthority,o=t.messageBus.serviceUrl,a=sharedAcpServer,n=sharedSessionMutationCoordinator;if(!(r&&r.cloudTargetInstanceId&&o&&a&&n))return sharedNativeCloudChat;const i=sharedNativeCloudChat??createNativeCloudChatComposition({authority:nativeCloudChatAuthorityFromRuntimeAuthority(r),serviceUrl:o,logger:e.logger});if(sharedNativeCloudChat=i,!t.messageBus.enabled)return i;const s=i,l=r;let c;const u=new Map,d=new RuntimeAuthorityMessageBusLifecycle({authority:l,logger:e.logger,bus:{connect:async t=>{c?.(),u.clear(),c=s.adapter.listen({eventTypes:["message.created"]},r=>{if(r.type===APPROVAL_DECISION_MESSAGE_TYPE&&r.senderId?.startsWith("user:")&&isApprovalDocument(r.content))return void sharedApprovalBridge.onDecision(r.content);if("user.continue"===r.type&&isQuestionResponseDocument(r.content))return void sharedQuestionBridge.onResponse(r);const o=(r.content??{}).metadata??{},i="string"==typeof o.target_agent_id?o.target_agent_id:"",l=i?((t,r)=>{const o=sharedAgentMappings.snapshot();if(o)for(const[i,l]of o.entries()){if(l.id!==r)continue;if(l.instanceId!==t.instanceId)continue;const o=`${i}\0${l.id}`;let c=u.get(o);return c||(c={localAgentId:i,inbound:createImInboundHandler({runtime:e.runtime,pluginConfig:e.pluginConfig,client:s.adapter,localServer:{getLocalAgentId:()=>i,resolveLocalAgentId:e=>e===l.id?i:void 0,getDefaultPlatformAgent:()=>({instanceId:t.instanceId}),ensureImInboundSession:(e,t,r,o)=>{a.ensureImInboundSession(e,t,r,o)},chatAbort:(e,t)=>a.chatAbort(e,t)},promptRunStore:sharedPromptRunStore,waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{}),assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,approvalStreams:sharedApprovalBridge,questionStreams:sharedQuestionBridge,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:n,logger:e.logger,writeObs:sharedWriteObs,principalIdOverride:t.instanceId,activeRunAuthority:a.getActiveRunAuthority(),applyTurnModel:(e,t)=>a.applyImTurnModel(e,t),restoreTurnModel:e=>a.restoreImTurnModel(e),...agentGateway?{completeA2ATask:(t,r,o)=>completeA2ATask({gateway:agentGateway,logger:e.logger},t,r,o)}:{}})},u.set(o,c)),c}})(t,i):void 0;if(!l)return void e.logger.warn?.(`[beeos-claw] native cloud chat dropped unresolvable target_agent_id=${i||"missing"} message_id=${r.id}`);("chat_cancel"===r.type?l.inbound.onChatCancel(r):l.inbound.onChatMessage(r)).catch(t=>{e.logger.error?.(`[beeos-claw] native cloud chat dispatch failed message_id=${r.id}: ${t instanceof Error?t.message:String(t)}`)})});try{await s.adapter.connect()}catch(e){throw c?.(),c=void 0,e}},disconnect:async()=>{c?.(),c=void 0,u.clear(),await s.adapter.disconnect()}}});return sharedNativeChatService={id:"beeos-native-cloud-chat",async start(){d.start()},async stop(){await d.stop()}},e.registerService(sharedNativeChatService),e.logger.info?.("[beeos-claw] native Cloud personal-chat composition registered"),i}const plugin={id:"beeos-claw",name:"beeos-claw",description:"BeeOS platform bridge plugin for OpenClaw. Provides file upload/download, ACP bridge, and observability.",version:PLUGIN_VERSION,register(e){if(_initializing)return;registerCentralNativeContextEngine(e),registerSandboxNativeActivation(e,()=>{if(!sharedSessionMutationCoordinator)throw new Error("native session writer coordinator is unavailable");return sharedSessionMutationCoordinator.activeMutationCount},createSandboxNativeTargetLookup(()=>sharedRuntimeAuthority,()=>sharedGatewayClient,{logger:e.logger}),async()=>{const e=sharedGatewayClient;if(!e)throw new Error("OpenClaw gateway is not connected");await e.waitForConnected(3e4),await e.request("secrets.reload",{})});const t=pluginCloudRuntimeTarget(e),r=void 0!==t&&t!==sharedRuntimeAuthority?.cloudTargetInstanceId,o=planPluginRegistration(e.registrationMode,_fullRuntimeRegistered,r);if("skip"!==o){_initializing=!0;try{if(!hasRuntimeReplyApi(e.runtime))throw e.logger.error?.("[beeos-claw] FATAL: OpenClaw runtime.channel.reply.dispatchReplyFromConfig not exposed. Upgrade OpenClaw or revert beeos-claw."),new Error("openclaw_runtime_reply_api_unavailable");const t=(t,r)=>{registerUploadTools(e,t,r),registerArouterLatencyRouting(e),registerArouterMediaProviders(e)};if("capabilities"===o&&sharedPluginContext){if(cachedCapabilityTools.length>0){const t=resolveCapabilityToolReplay({currentRegisterTool:e.registerTool,wrappedRegisterTool:wrappedRegisterTool,originalRegisterTool:rawRegisterTool}),r=replayCachedPluginTools((r,o)=>t.call(e,r,o),cachedCapabilityTools);return registerArouterLatencyRouting(e),registerArouterMediaProviders(e),void e.logger.info?.(`[beeos-claw] capability re-register mode=${e.registrationMode} tools_only count=${r}`)}const r={current:sharedAcpServer??null};return t(sharedPluginContext,r),registerServices(e,sharedPluginContext,r),void e.logger.info?.(`[beeos-claw] capability re-register mode=${e.registrationMode} capabilities_only`)}const r=initializePlugin(e);if(!r)return;const a={current:null};installUnhandledRejectionObserver(e,r.writeObs,a),ensureRegisterToolCache(e),cacheRuntimeRegistrations(e),cachedCapabilityTools.length=0,t(r,a),agentGateway&&(e.on?e.on("before_agent_finalize",async(e,t)=>{if(await fileDeliveryFinalizeDecision(e),!e.runId||!t?.runId||e.runId===t.runId)return nativeHtmlDeliveryForRun(e.runId??t?.runId)?.beforeFinalize(e)}):e.logger.warn?.("[file-delivery] OpenClaw plugin hooks unavailable; finalization check disabled")),registerServices(e,r,a),sharedPluginContext=r,marksFullRuntimeRegistered(e.registrationMode,o)&&(_fullRuntimeRegistered=!0),_pluginRegisteredAt=Date.now(),e.logger.info?.("[beeos-claw] Plugin registered successfully")}finally{_initializing=!1}}else if(!e.registrationMode||"full"===e.registrationMode){const t=resolveCapabilityToolReplay({currentRegisterTool:e.registerTool,wrappedRegisterTool:wrappedRegisterTool,originalRegisterTool:rawRegisterTool});replayCachedPluginTools((r,o)=>t.call(e,r,o),cachedCapabilityTools),replayRuntimeRegistrations(e),registerArouterLatencyRouting(e),registerArouterMediaProviders(e)}}};export default plugin;
@@ -1 +1 @@
1
- import{createHash}from"node:crypto";import{isDeepStrictEqual}from"node:util";export const CENTRAL_NATIVE_ENGINE_ID="beeos-central-chat";export const OPENCLAW_NATIVE_CODEC="openclaw-session-events-v1";export function nativePayloadDigest(e){const t=e=>Array.isArray(e)?e.map(t):null!==e&&"object"==typeof e?Object.fromEntries(Object.entries(e).sort(([e],[t])=>e<t?-1:e>t?1:0).map(([e,n])=>[e,t(n)])):e;return createHash("sha256").update(JSON.stringify(t(e))).digest("hex")}export function nativeBindingDigest(e){const{context:t,...n}=e;return nativePayloadDigest({...n,tenant_ref:t.tenant_ref,scope_ref:t.scope_ref})}export function assertCentralNativeReceipt(e,t){const n=e.wire,i=n.events;if(!Array.isArray(i)||i.some(e=>!e||"object"!=typeof e||"string"!=typeof e.event_id))throw new Error("central native append has invalid prepared State event identities");if(!(t.receipt_id&&t.idempotency_key===e.idempotencyKey&&t.payload_sha256===e.payloadDigest&&t.read_watermark&&t.operation_id===e.binding.operationId&&t.session_id===e.binding.sessionId&&t.history_generation===e.binding.historyGeneration&&t.branch_id===e.binding.branchId&&isDeepStrictEqual(t.writer,e.binding.writer)&&t.previous_watermark===e.expectedWatermark&&isDeepStrictEqual(t.terminal,n.terminal)&&isDeepStrictEqual(t.event_ids,i.map(e=>e.event_id))&&/^(0|[1-9][0-9]*)$/.test(t.read_watermark)&&t.read_watermark===String(BigInt(e.expectedWatermark)+BigInt(i.length))))throw new Error("central native append returned no matching durable transaction receipt")}export class CentralNativeContextEngine{options;info={id:"beeos-central-chat",name:"BeeOS central native chat",version:"1",failureMode:"strict",acceptedHostParams:["sessionKey","sessionTarget","runtimeContext","runtimeSettings","prompt"],transcriptSemantics:{currentTurnFence:"before-current-turn-entry-v1",turnAdvancementIdempotency:"atomic-idempotent-v1",nativeEvents:"lossless-v1"}};terminalOperations=new Set;loaded=new Map;constructor(e){this.options=e}source(e){const t=this.loaded.get(e);if(!t)throw new Error("central native session has no loaded source");return structuredClone(t)}forBindings(e){const t=new CentralNativeContextEngine({...this.options,resolveBinding:e});for(const[e,n]of this.loaded)t.loaded.set(e,structuredClone(n));for(const e of this.terminalOperations)t.terminalOperations.add(e);return t}binding(e){if(!e)throw new Error("central native session key is required");return this.options.resolveBinding(e)}async hydrateNativeSession(e){const t=this.binding(e.sessionKey);for(const e of await this.options.pending.list(t.sessionId)){const n=await this.options.store.receipt({...e,binding:{...e.binding,context:t.context}});if(!n)throw new Error("central native append outcome is unknown");this.acceptReceipt(e,n),await this.options.pending.complete(e,n)}const n=await this.options.store.load(t);if(n.codec!==OPENCLAW_NATIVE_CODEC||!Array.isArray(n.events)||!isDeepStrictEqual(n.writer,t.writer)||!n.watermark)throw new Error("central native load does not match the authorized codec/fence");return n.terminal?.response_id===t.responseId&&this.terminalOperations.add(t.operationId),this.loaded.set(e.sessionKey,structuredClone(n)),{events:structuredClone(n.events)}}async bootstrap(){return{bootstrapped:!0}}async ingest(){throw new Error("central native writes require an atomic native turn commit")}async assemble(e){if(this.binding(e.sessionKey),!e.sessionKey||!this.loaded.has(e.sessionKey))throw new Error("central native context was not hydrated by the pinned host");return{messages:e.messages,estimatedTokens:0}}async admitTurn(e){const{admission:t}=e,n=this.binding(t.sessionKey);if(this.terminalOperations.has(n.operationId))throw new Error("original Response is already terminal; new native admission is forbidden");const i=await this.options.readNativeEvents(t.sessionKey);if(!Number.isSafeInteger(t.rawSeq)||t.rawSeq<0||t.rawSeq>=i.length)throw new Error("native admission has no exact transcript row");await this.commitSnapshot(t.sessionKey,n,`admit:${n.operationId}:${t.logicalTurnId}`,i.slice(0,t.rawSeq+1),t)}nativeTranscriptBase(e){const t=this.source(e.sessionKey);return{eventCount:t.events.length,snapshotDigest:nativePayloadDigest(t.events),bindingDigest:nativeBindingDigest(this.binding(e.sessionKey))}}async commitTurn(e){const t=this.binding(e.sessionKey);if(!e.nativeEvents)throw new Error("pinned host omitted native transcript events");const n=e.nativeBase;if(n?.bindingDigest!==nativeBindingDigest(t))throw new Error("native accepted-turn binding changed");const i=0===n?.eventCount?[]:this.source(e.sessionKey).events;if(!n||!Number.isSafeInteger(n.eventCount)||n.eventCount<0||n.eventCount>i.length||nativePayloadDigest(i.slice(0,n.eventCount))!==n.snapshotDigest)throw new Error("native accepted-turn base differs from the exact central prefix");const a=[...i.slice(0,n.eventCount),...e.nativeEvents];if(!e.nativeOutcome)throw new Error("pinned host omitted actual native terminal outcome");return this.commitSnapshot(e.sessionKey,t,e.advancementKey,a,e.terminal,e.nativeOutcome)}async finalizeNativeOutcome(e){const t=this.binding(e.sessionKey),n=await this.options.readNativeEvents(e.sessionKey);await this.commitSnapshot(e.sessionKey,t,`outcome:${t.operationId}:${nativePayloadDigest(e.nativeOutcome)}`,n,e.terminal,e.nativeOutcome)}async commitSnapshot(e,t,n,i,a,r){return this.options.store.withWrite(t,()=>this.commitSnapshotUnserialized(e,t,n,i,a,r))}async commitSnapshotUnserialized(e,t,n,i,a,r){const s=await this.options.pending.completed(n);if(s){const{context:e,...o}=s.binding,{context:c,...d}=t;if(!isDeepStrictEqual(o,d)||e.tenant_ref!==c.tenant_ref||e.scope_ref!==c.scope_ref)throw new Error("central native duplicate binding changed");if(s.nativeSnapshotDigest!==nativePayloadDigest({events:i,nativeTerminalAnchor:a??null,nativeOutcome:r??null}))throw new Error("central native duplicate turn has different native events");const p=await this.options.store.receipt({binding:{...s.binding,context:t.context},idempotencyKey:n,payloadDigest:s.receipt.payload_sha256});if(!p||!isDeepStrictEqual(p,s.receipt))throw new Error("central native duplicate receipt is unavailable or changed");return p.terminal&&this.terminalOperations.add(s.binding.operationId),this.options.onReceipt?.(s.binding,p),{status:"duplicate"}}const o=await this.options.pending.get(n);if(o){const{context:e,...n}=o.binding,{context:s,...c}=t;if(!isDeepStrictEqual(n,c)||e.tenant_ref!==s.tenant_ref||e.scope_ref!==s.scope_ref||o.nativeSnapshotDigest!==nativePayloadDigest({events:i,nativeTerminalAnchor:a??null,nativeOutcome:r??null}))throw new Error("central native idempotency conflict: pending advancement changed");const d=await this.options.store.receipt({...o,binding:t});if(!d)throw new Error("central native append outcome is unknown");return this.acceptReceipt(o,d),await this.options.pending.complete(o,d),{status:"duplicate"}}if(!this.loaded.has(e))throw new Error("central native commit has no exact loaded source");const c=await this.options.store.load(t);if(c.codec!==OPENCLAW_NATIVE_CODEC||!isDeepStrictEqual(c.writer,t.writer))throw new Error("central native refreshed source changed its codec/writer");if(c.terminal?.response_id===t.responseId&&this.terminalOperations.add(t.operationId),this.loaded.set(e,structuredClone(c)),this.terminalOperations.has(t.operationId))throw new Error("original Response is already terminal; new native advancement is forbidden");if(i.length<c.events.length||!isDeepStrictEqual(i.slice(0,c.events.length),c.events))throw new Error("native cache diverged from the exact central transcript prefix");const d=nativePayloadDigest({events:i,nativeTerminalAnchor:a??null,nativeOutcome:r??null});let p=c;if(i.length===p.events.length&&!r)throw new Error("native advancement contains no new native events");let l=!1;for(;p.events.length<i.length||r&&!l;){const s=p.events.length,o=i.length-s,c=this.options.store.nativeEventCapacity(t,!1),h=this.options.store.nativeEventCapacity(t,Boolean(r)),m=r&&o>h?s+Math.min(c,o-1):Math.min(s+h,i.length),v=m===i.length?n:`${n}:native:${s}`,u={binding:t,expectedWatermark:p.watermark,idempotencyKey:v,nativeSnapshotDigest:d,events:i.slice(s,m),...a?{nativeTerminalAnchor:a}:{},...r&&m===i.length?{nativeOutcome:r}:{}},g=await this.options.pending.get(v),w=g??await this.options.store.prepareAppend(u),{context:f,...y}=w.binding,{context:E,...b}=t;if(w.idempotencyKey!==v||w.nativeSnapshotDigest!==u.nativeSnapshotDigest||w.expectedWatermark!==p.watermark||!isDeepStrictEqual(y,b)||f.tenant_ref!==E.tenant_ref||f.scope_ref!==E.scope_ref||!isDeepStrictEqual(w.events,u.events)||!isDeepStrictEqual(w.nativeOutcome,u.nativeOutcome))throw new Error("central native SDK changed the prepared native append identity");let _;if(g){const e=await this.options.store.receipt({...g,binding:t});if(!e)throw new Error("central native append outcome is unknown");_=e}else await this.options.pending.put(w),_=await this.options.store.append(w);this.acceptReceipt(w,_),p={...p,events:structuredClone(i.slice(0,m)),watermark:_.read_watermark},this.loaded.set(e,p),await this.options.pending.complete(w,_),l=Boolean(r&&m===i.length)}return{status:"committed"}}acceptReceipt(e,t){assertCentralNativeReceipt(e,t),t.terminal&&this.terminalOperations.add(e.binding.operationId),this.options.onReceipt?.(e.binding,t)}async compact(e){const t="string"==typeof e.sessionKey?e.sessionKey:void 0,n=this.binding(t);if(this.terminalOperations.has(n.operationId))return{ok:!0,compacted:!1,reason:"central terminal already committed; compaction requires another admitted operation"};const i=await this.options.compact(e);if(i.ok&&i.compacted){const e=await this.options.readNativeEvents(t);await this.commitSnapshot(t,n,`compact:${n.operationId}:${nativePayloadDigest(e)}`,e)}return i}}
1
+ import{createHash}from"node:crypto";import{isDeepStrictEqual}from"node:util";import{nativeUploadedFileIds}from"./central-native-output-files.js";export const CENTRAL_NATIVE_ENGINE_ID="beeos-central-chat";export const OPENCLAW_NATIVE_CODEC="openclaw-session-events-v1";export function nativePayloadDigest(e){const t=e=>Array.isArray(e)?e.map(t):null!==e&&"object"==typeof e?Object.fromEntries(Object.entries(e).sort(([e],[t])=>e<t?-1:e>t?1:0).map(([e,n])=>[e,t(n)])):e;return createHash("sha256").update(JSON.stringify(t(e))).digest("hex")}export function nativeBindingDigest(e){const{context:t,...n}=e;return nativePayloadDigest({...n,tenant_ref:t.tenant_ref,scope_ref:t.scope_ref})}export function assertCentralNativeReceipt(e,t){const n=e.wire,i=n.events;if(!Array.isArray(i)||i.some(e=>!e||"object"!=typeof e||"string"!=typeof e.event_id))throw new Error("central native append has invalid prepared State event identities");if(!(t.receipt_id&&t.idempotency_key===e.idempotencyKey&&t.payload_sha256===e.payloadDigest&&t.read_watermark&&t.operation_id===e.binding.operationId&&t.session_id===e.binding.sessionId&&t.history_generation===e.binding.historyGeneration&&t.branch_id===e.binding.branchId&&isDeepStrictEqual(t.writer,e.binding.writer)&&t.previous_watermark===e.expectedWatermark&&isDeepStrictEqual(t.terminal,n.terminal)&&isDeepStrictEqual(t.event_ids,i.map(e=>e.event_id))&&/^(0|[1-9][0-9]*)$/.test(t.read_watermark)&&t.read_watermark===String(BigInt(e.expectedWatermark)+BigInt(i.length))))throw new Error("central native append returned no matching durable transaction receipt")}export class CentralNativeContextEngine{options;info={id:"beeos-central-chat",name:"BeeOS central native chat",version:"1",failureMode:"strict",acceptedHostParams:["sessionKey","sessionTarget","runtimeContext","runtimeSettings","prompt"],transcriptSemantics:{currentTurnFence:"before-current-turn-entry-v1",turnAdvancementIdempotency:"atomic-idempotent-v1",nativeEvents:"lossless-v1"}};terminalOperations=new Set;loaded=new Map;constructor(e){this.options=e}source(e){const t=this.loaded.get(e);if(!t)throw new Error("central native session has no loaded source");return structuredClone(t)}forBindings(e){const t=new CentralNativeContextEngine({...this.options,resolveBinding:e});for(const[e,n]of this.loaded)t.loaded.set(e,structuredClone(n));for(const e of this.terminalOperations)t.terminalOperations.add(e);return t}binding(e){if(!e)throw new Error("central native session key is required");return this.options.resolveBinding(e)}async hydrateNativeSession(e){const t=this.binding(e.sessionKey);for(const e of await this.options.pending.list(t.sessionId)){const n=await this.options.store.receipt({...e,binding:{...e.binding,context:t.context}});if(!n)throw new Error("central native append outcome is unknown");this.acceptReceipt(e,n),await this.options.pending.complete(e,n)}const n=await this.options.store.load(t);if(n.codec!==OPENCLAW_NATIVE_CODEC||!Array.isArray(n.events)||!isDeepStrictEqual(n.writer,t.writer)||!n.watermark)throw new Error("central native load does not match the authorized codec/fence");return n.terminal?.response_id===t.responseId&&this.terminalOperations.add(t.operationId),this.loaded.set(e.sessionKey,structuredClone(n)),{events:structuredClone(n.events)}}async bootstrap(){return{bootstrapped:!0}}async ingest(){throw new Error("central native writes require an atomic native turn commit")}async assemble(e){if(this.binding(e.sessionKey),!e.sessionKey||!this.loaded.has(e.sessionKey))throw new Error("central native context was not hydrated by the pinned host");return{messages:e.messages,estimatedTokens:0}}async admitTurn(e){const{admission:t}=e,n=this.binding(t.sessionKey);if(this.terminalOperations.has(n.operationId))throw new Error("original Response is already terminal; new native admission is forbidden");const i=await this.options.readNativeEvents(t.sessionKey);if(!Number.isSafeInteger(t.rawSeq)||t.rawSeq<0||t.rawSeq>=i.length)throw new Error("native admission has no exact transcript row");await this.commitSnapshot(t.sessionKey,n,`admit:${n.operationId}:${t.logicalTurnId}`,i.slice(0,t.rawSeq+1),t)}nativeTranscriptBase(e){const t=this.source(e.sessionKey);return{eventCount:t.events.length,snapshotDigest:nativePayloadDigest(t.events),bindingDigest:nativeBindingDigest(this.binding(e.sessionKey))}}async commitTurn(e){const t=this.binding(e.sessionKey);if(!e.nativeEvents)throw new Error("pinned host omitted native transcript events");const n=e.nativeBase;if(n?.bindingDigest!==nativeBindingDigest(t))throw new Error("native accepted-turn binding changed");const i=0===n?.eventCount?[]:this.source(e.sessionKey).events;if(!n||!Number.isSafeInteger(n.eventCount)||n.eventCount<0||n.eventCount>i.length||nativePayloadDigest(i.slice(0,n.eventCount))!==n.snapshotDigest)throw new Error("native accepted-turn base differs from the exact central prefix");const a=[...i.slice(0,n.eventCount),...e.nativeEvents];if(!e.nativeOutcome)throw new Error("pinned host omitted actual native terminal outcome");return this.commitSnapshot(e.sessionKey,t,e.advancementKey,a,e.terminal,e.nativeOutcome,nativeUploadedFileIds(e.nativeEvents))}async finalizeNativeOutcome(e){const t=this.binding(e.sessionKey),n=await this.options.readNativeEvents(e.sessionKey);await this.commitSnapshot(e.sessionKey,t,`outcome:${t.operationId}:${nativePayloadDigest(e.nativeOutcome)}`,n,e.terminal,e.nativeOutcome)}async commitSnapshot(e,t,n,i,a,s,r){return this.options.store.withWrite(t,()=>this.commitSnapshotUnserialized(e,t,n,i,a,s,r))}async commitSnapshotUnserialized(e,t,n,i,a,s,r){const o=await this.options.pending.completed(n);if(o){const{context:e,...r}=o.binding,{context:c,...d}=t;if(!isDeepStrictEqual(r,d)||e.tenant_ref!==c.tenant_ref||e.scope_ref!==c.scope_ref)throw new Error("central native duplicate binding changed");if(o.nativeSnapshotDigest!==nativePayloadDigest({events:i,nativeTerminalAnchor:a??null,nativeOutcome:s??null}))throw new Error("central native duplicate turn has different native events");const p=await this.options.store.receipt({binding:{...o.binding,context:t.context},idempotencyKey:n,payloadDigest:o.receipt.payload_sha256});if(!p||!isDeepStrictEqual(p,o.receipt))throw new Error("central native duplicate receipt is unavailable or changed");return p.terminal&&this.terminalOperations.add(o.binding.operationId),this.options.onReceipt?.(o.binding,p),{status:"duplicate"}}const c=await this.options.pending.get(n);if(c){const{context:e,...n}=c.binding,{context:r,...o}=t;if(!isDeepStrictEqual(n,o)||e.tenant_ref!==r.tenant_ref||e.scope_ref!==r.scope_ref||c.nativeSnapshotDigest!==nativePayloadDigest({events:i,nativeTerminalAnchor:a??null,nativeOutcome:s??null}))throw new Error("central native idempotency conflict: pending advancement changed");const d=await this.options.store.receipt({...c,binding:t});if(!d)throw new Error("central native append outcome is unknown");return this.acceptReceipt(c,d),await this.options.pending.complete(c,d),{status:"duplicate"}}if(!this.loaded.has(e))throw new Error("central native commit has no exact loaded source");const d=await this.options.store.load(t);if(d.codec!==OPENCLAW_NATIVE_CODEC||!isDeepStrictEqual(d.writer,t.writer))throw new Error("central native refreshed source changed its codec/writer");if(d.terminal?.response_id===t.responseId&&this.terminalOperations.add(t.operationId),this.loaded.set(e,structuredClone(d)),this.terminalOperations.has(t.operationId))throw new Error("original Response is already terminal; new native advancement is forbidden");if(i.length<d.events.length||!isDeepStrictEqual(i.slice(0,d.events.length),d.events))throw new Error("native cache diverged from the exact central transcript prefix");const p=nativePayloadDigest({events:i,nativeTerminalAnchor:a??null,nativeOutcome:s??null});let l=d;if(i.length===l.events.length&&!s)throw new Error("native advancement contains no new native events");let h=!1;for(;l.events.length<i.length||s&&!h;){const o=l.events.length,c=i.length-o,d=this.options.store.nativeEventCapacity(t,!1),v=this.options.store.nativeEventCapacity(t,Boolean(s)),m=s&&c>v?o+Math.min(d,c-1):Math.min(o+v,i.length),u=m===i.length?n:`${n}:native:${o}`,g={binding:t,expectedWatermark:l.watermark,idempotencyKey:u,nativeSnapshotDigest:p,events:i.slice(o,m),...a?{nativeTerminalAnchor:a}:{},...s&&m===i.length?{nativeOutcome:s,nativeOutputFileIds:r??[]}:{}},w=await this.options.pending.get(u),f=w??await this.options.store.prepareAppend(g),{context:y,...E}=f.binding,{context:b,..._}=t;if(!(f.idempotencyKey===u&&f.nativeSnapshotDigest===g.nativeSnapshotDigest&&f.expectedWatermark===l.watermark&&isDeepStrictEqual(E,_)&&y.tenant_ref===b.tenant_ref&&y.scope_ref===b.scope_ref&&isDeepStrictEqual(f.events,g.events)&&isDeepStrictEqual(f.nativeOutcome,g.nativeOutcome)&&isDeepStrictEqual(f.nativeOutputFileIds,g.nativeOutputFileIds)))throw new Error("central native SDK changed the prepared native append identity");let D;if(w){const e=await this.options.store.receipt({...w,binding:t});if(!e)throw new Error("central native append outcome is unknown");D=e}else await this.options.pending.put(f),D=await this.options.store.append(f);this.acceptReceipt(f,D),l={...l,events:structuredClone(i.slice(0,m)),watermark:D.read_watermark},this.loaded.set(e,l),await this.options.pending.complete(f,D),h=Boolean(s&&m===i.length)}return{status:"committed"}}acceptReceipt(e,t){assertCentralNativeReceipt(e,t),t.terminal&&this.terminalOperations.add(e.binding.operationId),this.options.onReceipt?.(e.binding,t)}async compact(e){const t="string"==typeof e.sessionKey?e.sessionKey:void 0,n=this.binding(t);if(this.terminalOperations.has(n.operationId))return{ok:!0,compacted:!1,reason:"central terminal already committed; compaction requires another admitted operation"};const i=await this.options.compact(e);if(i.ok&&i.compacted){const e=await this.options.readNativeEvents(t);await this.commitSnapshot(t,n,`compact:${n.operationId}:${nativePayloadDigest(e)}`,e)}return i}}
@@ -1 +1 @@
1
- import{RUNTIME_HASH_DOMAINS}from"@beeos-ai/beeos-types/runtime";import{centralNativeRuntime}from"./central-native-runtime.js";import{createCentralNativeMemoryAttempt}from"./central-native-memory.js";import{createNativeOutputFileAttempt,registerNativeOutputRunContext}from"./native-output-file-attempt.js";import{preparedSandboxNativeExecution}from"./sandbox-native-activation.js";import{dispatchRuntimeReplyWithRoute}from"./reply-router.js";import{prepareNativePromptInput}from"./native-prompt-preflight.js";import{downloadNativeInputFile}from"./native-input-files.js";import{runtimeMessageHash}from"./runtime-message-channel-contract.js";import{createCentralNativeDeltaStream}from"./central-native-delta.js";import{bindCentralInteractions}from"./central-native-interactions.js";export function createCentralNativeHost(e){return{async run(t){t.assertCurrent(),t.signal.throwIfAborted();const n=preparedSandboxNativeExecution(t.params,t.binding),r=t.params.runtimeRunId;if("string"!=typeof r||!r)throw new Error("original native RunID is unavailable");const i=e.coordinator.tryStartExclusive({sessionKey:n.sessionKey,label:t.binding.operationId},"message_service");if(!i.ok)throw new Error("central native physical session is busy");const a=i.token;let s=!1;const o=new AbortController,l=AbortSignal.any([t.signal,o.signal]),p=createCentralNativeMemoryAttempt({binding:t.binding,signal:l,assertCurrent:t.assertCurrent}),d=runtimeMessageHash(RUNTIME_HASH_DOMAINS.params,{method:"session/prompt",params:t.params}),c=createNativeOutputFileAttempt({operationId:t.binding.operationId,requestMessageId:t.requestMessageId,paramsHash:d,activeRunRegistrationId:t.binding.operationId,responseId:t.binding.responseId,attemptId:t.binding.attemptId,sessionKey:n.sessionKey,getLease:()=>{const t=e.getLease();if(!t)throw new Error("central native output lease is unavailable");return t},assertAttempt:t.assertCurrent,signal:l}),m=registerNativeOutputRunContext({runId:r,sessionKey:n.sessionKey,operationId:t.binding.operationId,activeRunRegistrationId:t.binding.operationId,responseId:t.binding.responseId,attemptId:t.binding.attemptId}),u=new Set;let g;const I=(n,r)=>{if(centralNativeRuntime().receipt(t.binding.operationId)?.terminal)return;const i={type:"response.beeos.part",response_id:t.binding.responseId,kind:n,data:JSON.stringify(r)};let a;try{a=e.recordPublicEvent(t.binding,i)}catch(e){a=Promise.reject(e)}u.add(a),a.then(()=>u.delete(a),e=>{u.delete(a),g??=e,o.abort(e)})},b=createCentralNativeDeltaStream(t.binding,e.publishDelta,t=>{e.logger.warn?.(`central output delta was not published: ${t instanceof Error?t.name:"error"}`)}),v=()=>centralNativeRuntime().receipt(t.binding.operationId)?.terminal,y=e=>{v()||b.partial(e.text)},f=e=>{v()||b.block(e.text)},h=()=>{v()||b.beginMessage()};let w="";const R=(e,n)=>(t.assertCurrent(),"final"===e&&"string"==typeof n.text&&n.text.length>0&&(w=w?`${w}\n${n.text}`:n.text),I(e,n),!0),C={sendToolResult:e=>R("tool",e),sendBlockReply:e=>{const t=R("block",e);return t&&f(e),t},sendFinalReply:e=>R("final",e),waitForIdle:async()=>{},getQueuedCounts:()=>({tool:0,block:0,final:0}),markComplete:()=>{}};try{const i=t.params.parts,o=Array.isArray(i)?prepareNativePromptInput(i):"string"==typeof t.params.text?{message:t.params.text,files:[]}:void 0;if(!o)throw new Error("central native signed prompt parts are unavailable");await centralNativeRuntime().prepare(n.sessionKey,t.binding);const m=[],v=[];for(const n of o.files){t.assertCurrent();const r=e.getLease();if(!r)throw new Error("central native input Files lease is unavailable");const i=await e.inputFiles.resolve({operationId:t.binding.operationId,requestMessageId:t.requestMessageId,paramsHash:d,partIndex:n.partIndex,lease:r,signal:t.signal}),a=await downloadNativeInputFile({fileId:n.fileId,...i,signal:t.signal,assertAttempt:t.assertCurrent});m.push(a.path),v.push(a.mimeType)}let R;t.assertCurrent(),t.signal.throwIfAborted();const N=bindCentralInteractions(n.sessionKey,{responseId:t.binding.responseId,attemptId:t.binding.attemptId,mode:t.params.approvalMode,signal:l,publish:n=>e.recordPublicEvent(t.binding,{type:"response.interaction",response_id:t.binding.responseId,interaction:n}),decide:n=>e.decideInteraction(t.binding,n)});try{await dispatchRuntimeReplyWithRoute({runtime:{...e.runtime,config:{loadConfig:e.currentConfig}},preparedPrompt:{message:o.message,mediaPaths:m,mediaTypes:v,nativeSystemContext:n.systemPrompt},replyRoute:{protocol:"acp",requestId:t.binding.operationId,sessionId:n.sessionKey,sourceMessageId:t.requestMessageId,originatingChannel:"webchat",originatingTo:n.localAgentId,accountId:n.localAgentId,origin:"beeos-central-response"},replySinks:{acp:{dispatcher:C,replyOptions:{runId:r,abortSignal:l,disableBlockStreaming:!1,onAgentRunStart:t=>{e.coordinator.bindRun(a,t),p.bindHostRun(t),c.bindHostRun(t)},onPartialReply:y,onBlockReplyQueued:e=>{f(e)},onAssistantMessageStart:h,onReasoningStream:e=>{I("reasoning",e)},onToolStart:e=>{I("tool.start",e)},onItemEvent:e=>{I("item",e)}}}},onDispatchInvoked:()=>{s=!0}})}catch(e){R=e}try{await N()}catch(e){R??=e}await Promise.allSettled([...u,b.close()]),R??=g;const x=t.signal.aborted,S=centralNativeRuntime().receipt(t.binding.operationId)?.terminal,A=await e.coordinator.converge(a,x?"cancelled":"completed"===S?.status?"completed":"error");if(!A.ok)throw new Error("central native physical writer did not quiesce");if(t.assertCurrent(),!e.native.nativeWritersQuiescent({sessionKey:n.sessionKey}))throw new Error("central native admission still owns the physical writer");if(R&&!x)throw R;const E=centralNativeRuntime().receipt(t.binding.operationId)?.terminal;if(!E||E.response_id!==t.binding.responseId)throw new Error("native outcome has no original central terminal transaction receipt");const M=E.status;return t.assertCurrent(),e.coordinator.release(A.permit),{status:M,...w?{finalText:w}:{}}}catch(t){throw s?e.coordinator.snapshot(n.sessionKey)&&e.coordinator.requireRecovery(a,"terminal_not_observed"):e.coordinator.releaseBeforeRuntime(a),t}finally{p.close(),c.close(),m()}}}}
1
+ import{RUNTIME_HASH_DOMAINS}from"@beeos-ai/beeos-types/runtime";import{centralNativeRuntime}from"./central-native-runtime.js";import{createCentralNativeMemoryAttempt}from"./central-native-memory.js";import{createNativeOutputFileAttempt,registerNativeOutputRunContext}from"./native-output-file-attempt.js";import{preparedSandboxNativeExecution}from"./sandbox-native-activation.js";import{dispatchRuntimeReplyWithRoute}from"./reply-router.js";import{prepareNativePromptInput}from"./native-prompt-preflight.js";import{downloadNativeInputFile}from"./native-input-files.js";import{runtimeMessageHash}from"./runtime-message-channel-contract.js";import{createCentralNativeDeltaStream}from"./central-native-delta.js";import{bindCentralInteractions}from"./central-native-interactions.js";export function createCentralNativeHost(e){return{async run(t){t.assertCurrent(),t.signal.throwIfAborted();const n=preparedSandboxNativeExecution(t.params,t.binding),r=t.params.runtimeRunId;if("string"!=typeof r||!r)throw new Error("original native RunID is unavailable");const i=e.coordinator.tryStartExclusive({sessionKey:n.sessionKey,label:t.binding.operationId},"message_service");if(!i.ok)throw new Error("central native physical session is busy");const a=i.token;let s=!1;const o=new AbortController,l=AbortSignal.any([t.signal,o.signal]),p=createCentralNativeMemoryAttempt({binding:t.binding,signal:l,assertCurrent:t.assertCurrent}),d=runtimeMessageHash(RUNTIME_HASH_DOMAINS.params,{method:"session/prompt",params:t.params}),c=createNativeOutputFileAttempt({operationId:t.binding.operationId,requestMessageId:t.requestMessageId,paramsHash:d,activeRunRegistrationId:t.binding.operationId,responseId:t.binding.responseId,attemptId:t.binding.attemptId,sessionKey:n.sessionKey,getLease:()=>{const t=e.getLease();if(!t)throw new Error("central native output lease is unavailable");return t},assertAttempt:t.assertCurrent,signal:l}),m=registerNativeOutputRunContext({runId:r,sessionKey:n.sessionKey,operationId:t.binding.operationId,activeRunRegistrationId:t.binding.operationId,responseId:t.binding.responseId,attemptId:t.binding.attemptId}),u=new Set;let g;const I=(n,r)=>{if(centralNativeRuntime().receipt(t.binding.operationId)?.terminal)return;const i={type:"response.beeos.part",response_id:t.binding.responseId,kind:n,data:JSON.stringify(r)};let a;try{a=e.recordPublicEvent(t.binding,i)}catch(e){a=Promise.reject(e)}u.add(a),a.then(()=>u.delete(a),e=>{u.delete(a),g??=e,o.abort(e)})},b=createCentralNativeDeltaStream(t.binding,e.publishDelta,t=>{e.logger.warn?.(`central output delta was not published: ${t instanceof Error?t.name:"error"}`)}),v=()=>centralNativeRuntime().receipt(t.binding.operationId)?.terminal,y=e=>{v()||b.partial(e.text)},f=e=>{v()||b.block(e.text)},h=()=>{v()||b.beginMessage()};let w="";const R=(e,n)=>(t.assertCurrent(),"final"===e&&"string"==typeof n.text&&n.text.length>0&&(w=w?`${w}\n${n.text}`:n.text),I(e,n),!0),N={sendToolResult:e=>R("tool",e),sendBlockReply:e=>{const t=R("block",e);return t&&f(e),t},sendFinalReply:e=>R("final",e),waitForIdle:async()=>{},getQueuedCounts:()=>({tool:0,block:0,final:0}),markComplete:()=>{}};try{const i=t.params.parts,o=Array.isArray(i)?prepareNativePromptInput(i):"string"==typeof t.params.text?{message:t.params.text,files:[]}:void 0;if(!o)throw new Error("central native signed prompt parts are unavailable");await centralNativeRuntime().prepare(n.sessionKey,t.binding);const m=[],v=[];for(const n of o.files){t.assertCurrent();const r=e.getLease();if(!r)throw new Error("central native input Files lease is unavailable");const i=await e.inputFiles.resolve({operationId:t.binding.operationId,requestMessageId:t.requestMessageId,paramsHash:d,partIndex:n.partIndex,lease:r,signal:t.signal}),a=await downloadNativeInputFile({fileId:n.fileId,...i,signal:t.signal,assertAttempt:t.assertCurrent});m.push(a.path),v.push(a.mimeType)}let R;t.assertCurrent(),t.signal.throwIfAborted();const C=bindCentralInteractions(n.sessionKey,{responseId:t.binding.responseId,attemptId:t.binding.attemptId,mode:t.params.approvalMode,signal:l,publish:n=>e.recordPublicEvent(t.binding,{type:"response.interaction",response_id:t.binding.responseId,interaction:n}),decide:n=>e.decideInteraction(t.binding,n)});try{await dispatchRuntimeReplyWithRoute({runtime:{...e.runtime,config:{current:e.currentConfig}},preparedPrompt:{message:o.message,mediaPaths:m,mediaTypes:v,nativeSystemContext:n.systemPrompt},replyRoute:{protocol:"acp",requestId:t.binding.operationId,sessionId:n.sessionKey,sourceMessageId:t.requestMessageId,originatingChannel:"webchat",originatingTo:n.localAgentId,accountId:n.localAgentId,origin:"beeos-central-response"},replySinks:{acp:{dispatcher:N,replyOptions:{runId:r,abortSignal:l,disableBlockStreaming:!1,onAgentRunStart:t=>{e.coordinator.bindRun(a,t),p.bindHostRun(t),c.bindHostRun(t)},onPartialReply:y,onBlockReplyQueued:e=>{f(e)},onAssistantMessageStart:h,onReasoningStream:e=>{I("reasoning",e)},onToolStart:e=>{I("tool.start",e)},onItemEvent:e=>{I("item",e)}}}},onDispatchInvoked:()=>{s=!0}})}catch(e){R=e}try{await C()}catch(e){R??=e}await Promise.allSettled([...u,b.close()]),R??=g;const x=t.signal.aborted,S=centralNativeRuntime().receipt(t.binding.operationId)?.terminal,A=await e.coordinator.converge(a,x?"cancelled":"completed"===S?.status?"completed":"error");if(!A.ok)throw new Error("central native physical writer did not quiesce");if(t.assertCurrent(),!e.native.nativeWritersQuiescent({sessionKey:n.sessionKey}))throw new Error("central native admission still owns the physical writer");if(R&&!x)throw R;const E=centralNativeRuntime().receipt(t.binding.operationId)?.terminal;if(!E||E.response_id!==t.binding.responseId)throw new Error("native outcome has no original central terminal transaction receipt");const M=E.status;return t.assertCurrent(),e.coordinator.release(A.permit),{status:M,...w?{finalText:w}:{}}}catch(t){throw s?e.coordinator.snapshot(n.sessionKey)&&e.coordinator.requireRecovery(a,"terminal_not_observed"):e.coordinator.releaseBeforeRuntime(a),t}finally{p.close(),c.close(),m()}}}}
@@ -1 +1 @@
1
- import{HarnessProtocolError}from"@beeos-ai/cloud-harness-sdk";import{parseBeeosFileUri}from"../files/beeos-file-uri.js";const object=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),fileIdPattern=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;export class NativeArtifactDeliveryFailure extends Error{constructor(){super("The native output artifact could not be delivered.")}}export function nativeOutputFileIds(e){const t=[];if(void 0!==e.mediaUrl&&null!==e.mediaUrl&&""!==e.mediaUrl&&t.push(e.mediaUrl),void 0!==e.mediaUrls&&null!==e.mediaUrls){if(!Array.isArray(e.mediaUrls))throw new NativeArtifactDeliveryFailure;t.push(...e.mediaUrls)}return t.map(e=>{const t="string"==typeof e?parseBeeosFileUri(e).fileId:void 0;if(!t||e!==`beeos-file://${t}`||!fileIdPattern.test(t)||"00000000-0000-0000-0000-000000000000"===t)throw new NativeArtifactDeliveryFailure;return t})}function isDefiniteFileNotFound(e){if(!(e instanceof HarnessProtocolError&&404===e.status&&e.body))return!1;let t;try{t=JSON.parse(e.body)}catch{return!1}return object(t)&&"not_found"===t.code&&"file not found"===t.message}export function centralNativeOutputFileResolver(e,t){return async(i,r)=>{const a=await t.credential(i),n=t.outputFileBinding(i);let s;try{s=await e.resolveOutput(a,i.operationId,{...n,fileId:r})}catch(e){if(t.outputFileBinding(i),isDefiniteFileNotFound(e))throw new NativeArtifactDeliveryFailure;throw e}if(t.outputFileBinding(i),!object(s)||s.operationId!==i.operationId||s.requestMessageId!==n.requestMessageId||s.paramsHash!==n.paramsHash||s.activeRunRegistrationId!==n.activeRunRegistrationId||!object(s.file))throw new Error("native output Files response binding invalid");const o=s.file;if(o.file_id!==r||"ready"!==o.status||"string"!=typeof o.filename||!o.filename||"string"!=typeof o.content_type||!o.content_type||"number"!=typeof o.size_bytes||!Number.isSafeInteger(o.size_bytes)||o.size_bytes<0||"string"!=typeof o.checksum_sha256||!/^[0-9a-f]{64}$/.test(o.checksum_sha256)||"string"!=typeof o.created_at||!Number.isFinite(Date.parse(o.created_at)))throw new Error("native output Files metadata invalid");if([...o.filename].length>256||[...o.content_type].length>128||o.size_bytes>67108864)throw new NativeArtifactDeliveryFailure;return{id:r,filename:o.filename,media_type:o.content_type,size_bytes:o.size_bytes,sha256:o.checksum_sha256,status:"ready",owner_scope:"org",owner_id:null,created_at:o.created_at,expires_at:null}}}
1
+ import{isDeepStrictEqual}from"node:util";import{HarnessProtocolError}from"@beeos-ai/cloud-harness-sdk";import{parseBeeosFileUri}from"../files/beeos-file-uri.js";import{confirmedUploadResourceLinks}from"../upload/tool-artifact-enrichment.js";const object=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),fileIdPattern=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;export class NativeArtifactDeliveryFailure extends Error{constructor(){super("The native output artifact could not be delivered.")}}export function nativeOutputFileIds(e){const t=[];if(void 0!==e.mediaUrl&&null!==e.mediaUrl&&""!==e.mediaUrl&&t.push(e.mediaUrl),void 0!==e.mediaUrls&&null!==e.mediaUrls){if(!Array.isArray(e.mediaUrls))throw new NativeArtifactDeliveryFailure;t.push(...e.mediaUrls)}return t.map(e=>{const t="string"==typeof e?parseBeeosFileUri(e).fileId:void 0;if(!t||e!==`beeos-file://${t}`||!fileIdPattern.test(t)||"00000000-0000-0000-0000-000000000000"===t)throw new NativeArtifactDeliveryFailure;return t})}export function nativeUploadedFileIds(e){const t=new Map,i=new Set,r=[],o=new Set;for(const[o,a]of e.entries()){if(!object(a)||"message"!==a.type||!object(a.message))continue;const e=a.message;if("assistant"===e.role&&Array.isArray(e.content))for(const r of e.content){if(!object(r)||"toolCall"!==r.type||"string"!=typeof r.id||"string"!=typeof r.name||!object(r.arguments))continue;const e={name:r.name,params:r.arguments},a=t.get(r.id);a&&!isDeepStrictEqual({name:a.name,params:a.params},e)&&i.add(r.id),a||t.set(r.id,{...e,index:o})}"toolResult"===e.role&&r.push({message:e,index:o})}for(const{message:e,index:a}of r){if(!0===e.isError||"string"!=typeof e.toolCallId||i.has(e.toolCallId))continue;const r=t.get(e.toolCallId);if(!r||r.index>=a||e.toolName!==r.name)continue;const n=confirmedUploadResourceLinks({toolCallId:e.toolCallId,toolName:r.name,params:r.params,rawResult:"beeos_upload_file"===r.name?e.details:e});for(const e of n){const t=parseBeeosFileUri(e.uri).fileId;t&&e.uri===`beeos-file://${t}`&&fileIdPattern.test(t)&&"00000000-0000-0000-0000-000000000000"!==t&&o.add(t)}}return[...o]}function isDefiniteFileNotFound(e){if(!(e instanceof HarnessProtocolError&&404===e.status&&e.body))return!1;let t;try{t=JSON.parse(e.body)}catch{return!1}return object(t)&&"not_found"===t.code&&"file not found"===t.message}export function centralNativeOutputFileResolver(e,t){return async(i,r)=>{const o=await t.credential(i),a=t.outputFileBinding(i);let n;try{n=await e.resolveOutput(o,i.operationId,{...a,fileId:r})}catch(e){if(t.outputFileBinding(i),isDefiniteFileNotFound(e))throw new NativeArtifactDeliveryFailure;throw e}if(t.outputFileBinding(i),!object(n)||n.operationId!==i.operationId||n.requestMessageId!==a.requestMessageId||n.paramsHash!==a.paramsHash||n.activeRunRegistrationId!==a.activeRunRegistrationId||!object(n.file))throw new Error("native output Files response binding invalid");const s=n.file;if(s.file_id!==r||"ready"!==s.status||"string"!=typeof s.filename||!s.filename||"string"!=typeof s.content_type||!s.content_type||"number"!=typeof s.size_bytes||!Number.isSafeInteger(s.size_bytes)||s.size_bytes<0||"string"!=typeof s.checksum_sha256||!/^[0-9a-f]{64}$/.test(s.checksum_sha256)||"string"!=typeof s.created_at||!Number.isFinite(Date.parse(s.created_at)))throw new Error("native output Files metadata invalid");if([...s.filename].length>256||[...s.content_type].length>128||s.size_bytes>67108864)throw new NativeArtifactDeliveryFailure;return{id:r,filename:s.filename,media_type:s.content_type,size_bytes:s.size_bytes,sha256:s.checksum_sha256,status:"ready",owner_scope:"org",owner_id:null,created_at:s.created_at,expires_at:null}}}
@@ -1 +1 @@
1
- import{createHash}from"node:crypto";import{isDeepStrictEqual}from"node:util";import{ChatStoreHttpError,chatAppendDigest,decodeNativeChatEvent,encodeNativeChatEvent}from"@beeos-ai/cloud-harness-sdk";import{OPENCLAW_NATIVE_CODEC,assertCentralNativeReceipt,nativePayloadDigest}from"./central-native-context-engine.js";import{generatedSessionName}from"./central-native-titles.js";import{nativeOutputFileIds,NativeArtifactDeliveryFailure}from"./central-native-output-files.js";const codec={name:"openclaw-session-events",version:"1"};export const CENTRAL_RESPONSE_CONTROL_CODEC={name:"beeos-response-control",version:"1"};const executionObservationType="response.beeos.execution_observation",decimal=e=>"string"==typeof e&&/^(0|[1-9][0-9]*)$/.test(e),key=e=>JSON.stringify([e.context.tenant_ref,e.context.scope_ref,e.sessionId,e.historyGeneration,e.branchId]),operationKey=e=>JSON.stringify([key(e),e.operationId,e.responseId,e.attemptId]),object=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),publicId=e=>"string"==typeof e&&/^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/.test(e)?e:null;export function publicModelRoute(e,t){if("string"==typeof e&&e.includes("/")){const t=e.indexOf("/");return[publicId(e.slice(0,t)),publicId(e.slice(t+1))]}return[publicId(t),publicId(e)]}function executedRoute(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.terminalReceipt)?t.terminalReceipt:{},i=object(n.effective)?n.effective:{},r=object(e.meta.executionTrace)?e.meta.executionTrace:{};return"string"==typeof i.responseModel?i.responseModel:"string"==typeof r.winnerModel?r.winnerModel:i.model}export function publicModelId(e){if("string"==typeof e&&0!==e.length)return publicId(e.includes("/")?`arouter_${e.replaceAll("/","_")}`:e)??void 0}function executedFacts(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.terminalReceipt)?t.terminalReceipt:{},i=object(n.effective)?n.effective:{},r=object(e.meta.executionTrace)?e.meta.executionTrace:{},o=object(e.meta.requestShaping)?e.meta.requestShaping:{},a="string"==typeof n.runId?n.runId:void 0,[s,d]=publicModelRoute(executedRoute(e),"string"==typeof i.provider?i.provider:r.winnerProvider);if(a&&s&&d)return{nativeRunId:a,facts:{actual_provider_id:s,actual_model_id:d,..."boolean"==typeof r.fallbackUsed?{fallback_used:r.fallbackUsed}:{},..."string"==typeof o.reasoning?{reasoning:o.reasoning}:{}}}}function terminalOutputItem(e){const t="string"==typeof e.toolCallId?e.toolCallId:"string"==typeof e.tool_call_id?e.tool_call_id:void 0,n="string"==typeof e.toolName?e.toolName:"string"==typeof e.tool_name?e.tool_name:void 0;if(t||n){if(!t||!n)throw new Error("native tool result lacks its tool call identity");return{type:"tool_summary",tool_call_id:t,tool_name:n,outcome:!0===e.isError?"failed":!1===e.isError?"succeeded":"unknown",summary:"string"==typeof e.text?e.text.slice(0,4096):""}}return"string"==typeof e.text&&e.text.length>0?{type:"output_text",text:e.text}:void 0}function terminalUsage(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.usage)?t.usage:void 0;if(!n)return;const i=e=>"number"==typeof e&&Number.isSafeInteger(e)&&e>=0?e:void 0,r=i(n.input),o=i(n.output);if(void 0===r&&void 0===o)return;const a=publicModelId(executedRoute(e));return{input_tokens:r??0,output_tokens:o??0,source:"provider",...a?{actual_model_id:a}:{}}}async function terminalProjection(e,t,n){const i=t.outcome;let r=["cancelled","aborted","superseded"].includes(i.reason)?"cancelled":["hard_timeout","timed_out","abandoned"].includes(i.reason)||["max_tokens","length","max_output_tokens"].includes(i.stopReason??"")?"incomplete":"completed"===i.reason&&"ok"===i.status?"completed":"failed";const o=[];let a;const s=new Set;try{for(const i of t.payloads){if(!object(i))throw new Error("native terminal payload is not a typed reply");const t=terminalOutputItem(i);t&&o.push(t);for(const t of nativeOutputFileIds(i))if(!s.has(t)){if(!n)throw new Error("authorized native output Files resolver is unavailable");o.push({type:"output_file",file:await n(e,t)}),s.add(t)}}}catch(e){if(!(e instanceof NativeArtifactDeliveryFailure))throw e;a=e,"completed"===r&&(r="failed")}const d=object(t.meta.agentMeta)?t.meta.agentMeta:{},c=terminalUsage(t);return{status:r,event:{type:"cancelled"===r?"response.failed":`response.${r}`,response:{id:e.responseId,status:r,output:o,..."string"==typeof d.model&&d.model.length>0?{model:d.model}:{},...c?{usage:c}:{},error:"failed"===r?{type:"harness_error",code:a?"artifact_delivery_failed":"harness_error",message:a?.message??(i.error||"The native harness could not complete this response.")}:null,incomplete_details:"incomplete"===r?{reason:"completed"===i.reason?"max_output_tokens":"runtime_interrupted"}:null}}}}export class StateCentralNativeStore{client;credential;titles;resolveOutputFile;writes=new Map;heads=new Map;publicEvents=new Map;memoryReads=new Map;executionObservations=new Map;constructor(e,t,n,i){this.client=e,this.credential=t,this.titles=n,this.resolveOutputFile=i}async recordGeneratedTitle(e,t){if(!this.titles)throw new Error("generated Session titles are unavailable");const n=generatedSessionName(t);if(!n)throw new Error("generated Session title is empty");return await this.titles.title(await this.credential(e),{context:e.context,session_id:e.sessionId,history_generation:e.historyGeneration,branch_id:e.branchId,name:n,idempotency_key:`title:${e.operationId}`})}withWrite(e,t){const n=key(e),i=(this.writes.get(n)??Promise.resolve()).then(t);return this.writes.set(n,i),i}async commitPublicProgress(e,t){await this.withWrite(e,async()=>{if(!this.publicEvents.get(operationKey(e))?.length)return;if(0!==(await t.list(e.sessionId)).length)throw new Error("native progress has unresolved original writes");const n=await this.load(e);if(n.terminal?.response_id===e.responseId)throw new Error("original native Response is already terminal");const i=structuredClone(this.publicEvents.get(operationKey(e))??[]),r=nativePayloadDigest(i),o=await this.prepareAppend({binding:e,events:[],expectedWatermark:n.watermark,publicProgress:!0,idempotencyKey:`progress:${e.operationId}:${n.watermark}:${r}`,nativeSnapshotDigest:r});await t.put(o);const a=await this.append(o);assertCentralNativeReceipt(o,a),await t.complete(o,a)})}recordPublicEvent(e,t){const n=operationKey(e),i=this.publicEvents.get(n)??[];i.push(structuredClone(t)),this.publicEvents.set(n,i)}recordMemoryRead(e,t){if("read"===t.status&&!t.watermark)throw new Error("actual Memory recall omitted its read watermark");this.memoryReads.set(operationKey(e),structuredClone(t))}bindExecutionObservation(e,t){if(t.admission.attemptId!==e.attemptId)throw new Error("native observation does not bind the original attempt");const n=operationKey(e),i=this.executionObservations.get(n);if(i&&!isDeepStrictEqual(i.source,t))throw new Error("native loaded observation changed");i||this.executionObservations.set(n,{source:structuredClone(t),loaded:!1})}nativeEventCapacity(e,t){const n=this.executionObservations.get(operationKey(e));return 200-(t?1:0)-(n&&!n.loaded?1:0)}async load(e){let t=null,n="0",i=null;const r=[];for(;;){const o=await this.client.load(await this.credential(e),{context:e.context,session_id:e.sessionId,history_generation:e.historyGeneration,branch_id:e.branchId,watermark:t,after:n,limit:200});this.assertPage(o,e,t,n),t=o.watermark;for(const e of o.events){if(e.sequence!==String(BigInt(n)+1n))throw new Error("central native event sequence has a gap");const t=decodeNativeChatEvent(e);if(isDeepStrictEqual(e.codec,codec))r.push(JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(t)));else if(!isDeepStrictEqual(e.codec,CENTRAL_RESPONSE_CONTROL_CODEC))throw new Error("central native event codec is not supported by this pinned Harness");n=e.sequence,i=e.event_id}if(o.next_after!==n||o.has_more&&BigInt(n)>=BigInt(t))throw new Error("central native page cursor does not match its fixed source");if(!o.has_more){if(n!==t)throw new Error("central native source ended before its fixed watermark");return this.heads.set(key(e),{watermark:t,lastEventId:i}),{codec:OPENCLAW_NATIVE_CODEC,events:r,watermark:t,writer:o.writer,terminal:o.terminal}}if(0===o.events.length)throw new Error("central native source made no page progress")}}async prepareAppend(e){if((e=structuredClone(e)).events.length>this.nativeEventCapacity(e.binding,Boolean(e.nativeOutcome)))throw new Error("native suffix must reserve its actual observation and terminal control rows");const t=this.heads.get(key(e.binding));if(!t||t.watermark!==e.expectedWatermark)throw new Error("native append has no exact loaded central source");let n=t.lastEventId;const i=e.events.map((t,i)=>{const r=Buffer.from(JSON.stringify(t),"utf8"),o=createHash("sha256").update(JSON.stringify([e.binding.sessionId,e.binding.historyGeneration,e.binding.branchId,String(BigInt(e.expectedWatermark)+BigInt(i)+1n)])).update(r).digest("hex"),a=encodeNativeChatEvent({eventId:`oc-${o}`,parentId:n,kind:t&&"object"==typeof t&&"type"in t&&"string"==typeof t.type?t.type:"native",codec:codec,content:r});return n=a.event_id,a});let r=null;const o=structuredClone(this.publicEvents.get(operationKey(e.binding))??[]),a=this.executionObservations.get(operationKey(e.binding)),s=(t,n,i)=>{const r=a.source,s="executed"===t?this.memoryReads.get(operationKey(e.binding)):void 0;o.push({type:executionObservationType,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,resolved_request_hash:r.resolvedRequestHash,payload:{phase:t,attempt:{...r.admission,...i?{nativeRunId:i.nativeRunId}:{}},read_watermark:r.readWatermark,source_ref:{id:n.event_id,digest:n.sha256},session_config_receipt:"loaded"===t?r.sessionConfigReceipt:null,runtime:null,partial_effective:{...r.loadedFacts,...i?.facts??{},...s?{memory_observation:s.status,memory_read_watermark:s.watermark}:{}}}})};if(a&&!a.loaded){const t=Buffer.from(JSON.stringify({type:"configuration.applied",...a.source}),"utf8"),r=`oc-loaded-${createHash("sha256").update(e.idempotencyKey).update(t).digest("hex")}`,o=encodeNativeChatEvent({eventId:r,parentId:n,kind:"configuration.applied",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:t});i.push(o),n=r,s("loaded",o)}if(e.publicProgress){if(e.nativeOutcome||0!==e.events.length||0===o.length)throw new Error("public native progress has invalid effect shape");const t=Buffer.from(JSON.stringify({type:"response.progress",response_id:e.binding.responseId,operation_id:e.binding.operationId,public_events_sha256:nativePayloadDigest(o)}),"utf8"),r=`oc-progress-${createHash("sha256").update(e.idempotencyKey).digest("hex")}`;i.push(encodeNativeChatEvent({eventId:r,parentId:n,kind:"response.progress",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:t})),n=r}if(e.nativeOutcome){const t=await terminalProjection(e.binding,e.nativeOutcome,this.resolveOutputFile),d=`oc-terminal-${createHash("sha256").update(e.idempotencyKey).digest("hex")}`,c={type:"response.terminal",operation_id:e.binding.operationId,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,native_outcome:e.nativeOutcome},l=encodeNativeChatEvent({eventId:d,parentId:n,kind:"response.terminal",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:Buffer.from(JSON.stringify(c),"utf8")});i.push(l),r={response_id:e.binding.responseId,status:t.status,event_id:d};const p=a?executedFacts(e.nativeOutcome):void 0;p&&s("executed",l,p),o.push(t.event)}const d={context:e.binding.context,session_id:e.binding.sessionId,history_generation:e.binding.historyGeneration,branch_id:e.binding.branchId,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,public_events:o,writer:e.binding.writer,expected_watermark:e.expectedWatermark,operation_id:e.binding.operationId,idempotency_key:e.idempotencyKey,events:i,terminal:r},c=chatAppendDigest(d),l={...d,payload_sha256:c};return{...structuredClone(e),codec:OPENCLAW_NATIVE_CODEC,payloadDigest:c,wire:l}}async append(e){const t=e.wire;if(chatAppendDigest(t)!==e.payloadDigest||t.payload_sha256!==e.payloadDigest)throw new Error("pending native append no longer matches its original digest");const n=await this.client.append(await this.credential(e.binding),t);return this.accept(e.binding,t,n),n}async receipt(e){const t=e.binding;try{const n=await this.client.receipt(await this.credential(t),{context:t.context,session_id:t.sessionId,history_generation:t.historyGeneration,branch_id:t.branchId,idempotency_key:e.idempotencyKey,payload_sha256:e.payloadDigest});if(n.operation_id!==t.operationId||!isDeepStrictEqual(n.writer,t.writer))throw new Error("original native receipt belongs to another operation/writer");return n}catch(e){if(e instanceof ChatStoreHttpError&&404===e.status&&"not_found"===e.code)return null;throw e}}assertPage(e,t,n,i){if(e.session_id!==t.sessionId||e.history_generation!==t.historyGeneration||e.branch_id!==t.branchId||!decimal(e.watermark)||null!==n&&e.watermark!==n||BigInt(e.watermark)<BigInt(i)||!Array.isArray(e.events)||"boolean"!=typeof e.has_more||!isDeepStrictEqual(e.writer,t.writer))throw new Error("central native load does not match the authorized fixed source/writer")}accept(e,t,n){if(!(n.operation_id===e.operationId&&n.previous_watermark===t.expected_watermark&&decimal(n.read_watermark)&&n.read_watermark===String(BigInt(t.expected_watermark)+BigInt(t.events.length))&&isDeepStrictEqual(n.event_ids,t.events.map(e=>e.event_id))&&isDeepStrictEqual(n.terminal,t.terminal)&&isDeepStrictEqual(n.writer,e.writer)))throw new Error("native append returned a receipt for different committed content");const i=this.heads.get(key(e));this.heads.set(key(e),{watermark:n.read_watermark,lastEventId:n.event_ids.at(-1)??i?.lastEventId??null});const r=operationKey(e),o=this.executionObservations.get(r);o&&t.public_events.some(e=>e.type===executionObservationType&&object(e.payload)&&"loaded"===e.payload.phase)&&(o.loaded=!0);const a=this.publicEvents.get(r);if(a){const e=t.public_events.filter(e=>e.type!==executionObservationType),i=e.slice(0,e.length-(t.terminal?1:0));if(!isDeepStrictEqual(a.slice(0,i.length),i))throw new Error("confirmed public events differ from their pending native buffer");n.terminal||a.length===i.length?this.publicEvents.delete(r):this.publicEvents.set(r,a.slice(i.length))}}}
1
+ import{createHash}from"node:crypto";import{isDeepStrictEqual}from"node:util";import{ChatStoreHttpError,chatAppendDigest,decodeNativeChatEvent,encodeNativeChatEvent}from"@beeos-ai/cloud-harness-sdk";import{OPENCLAW_NATIVE_CODEC,assertCentralNativeReceipt,nativePayloadDigest}from"./central-native-context-engine.js";import{generatedSessionName}from"./central-native-titles.js";import{nativeOutputFileIds,NativeArtifactDeliveryFailure}from"./central-native-output-files.js";const codec={name:"openclaw-session-events",version:"1"};export const CENTRAL_RESPONSE_CONTROL_CODEC={name:"beeos-response-control",version:"1"};const executionObservationType="response.beeos.execution_observation",decimal=e=>"string"==typeof e&&/^(0|[1-9][0-9]*)$/.test(e),key=e=>JSON.stringify([e.context.tenant_ref,e.context.scope_ref,e.sessionId,e.historyGeneration,e.branchId]),operationKey=e=>JSON.stringify([key(e),e.operationId,e.responseId,e.attemptId]),object=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),publicId=e=>"string"==typeof e&&/^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/.test(e)?e:null;export function publicModelRoute(e,t){if("string"==typeof e&&e.includes("/")){const t=e.indexOf("/");return[publicId(e.slice(0,t)),publicId(e.slice(t+1))]}return[publicId(t),publicId(e)]}function executedRoute(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.terminalReceipt)?t.terminalReceipt:{},i=object(n.effective)?n.effective:{},r=object(e.meta.executionTrace)?e.meta.executionTrace:{};return"string"==typeof i.responseModel?i.responseModel:"string"==typeof r.winnerModel?r.winnerModel:i.model}export function publicModelId(e){if("string"==typeof e&&0!==e.length)return publicId(e.includes("/")?`arouter_${e.replaceAll("/","_")}`:e)??void 0}function executedFacts(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.terminalReceipt)?t.terminalReceipt:{},i=object(n.effective)?n.effective:{},r=object(e.meta.executionTrace)?e.meta.executionTrace:{},o=object(e.meta.requestShaping)?e.meta.requestShaping:{},a="string"==typeof n.runId?n.runId:void 0,[s,d]=publicModelRoute(executedRoute(e),"string"==typeof i.provider?i.provider:r.winnerProvider);if(a&&s&&d)return{nativeRunId:a,facts:{actual_provider_id:s,actual_model_id:d,..."boolean"==typeof r.fallbackUsed?{fallback_used:r.fallbackUsed}:{},..."string"==typeof o.reasoning?{reasoning:o.reasoning}:{}}}}function terminalOutputItem(e){const t="string"==typeof e.toolCallId?e.toolCallId:"string"==typeof e.tool_call_id?e.tool_call_id:void 0,n="string"==typeof e.toolName?e.toolName:"string"==typeof e.tool_name?e.tool_name:void 0;if(t||n){if(!t||!n)throw new Error("native tool result lacks its tool call identity");return{type:"tool_summary",tool_call_id:t,tool_name:n,outcome:!0===e.isError?"failed":!1===e.isError?"succeeded":"unknown",summary:"string"==typeof e.text?e.text.slice(0,4096):""}}return"string"==typeof e.text&&e.text.length>0?{type:"output_text",text:e.text}:void 0}function terminalUsage(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.usage)?t.usage:void 0;if(!n)return;const i=e=>"number"==typeof e&&Number.isSafeInteger(e)&&e>=0?e:void 0,r=i(n.input),o=i(n.output);if(void 0===r&&void 0===o)return;const a=publicModelId(executedRoute(e));return{input_tokens:r??0,output_tokens:o??0,source:"provider",...a?{actual_model_id:a}:{}}}async function terminalProjection(e,t,n,i=[]){const r=t.outcome;let o=["cancelled","aborted","superseded"].includes(r.reason)?"cancelled":["hard_timeout","timed_out","abandoned"].includes(r.reason)||["max_tokens","length","max_output_tokens"].includes(r.stopReason??"")?"incomplete":"completed"===r.reason&&"ok"===r.status?"completed":"failed";const a=[];let s;const d=new Set,c=async t=>{if(!d.has(t)){if(!n)throw new Error("authorized native output Files resolver is unavailable");a.push({type:"output_file",file:await n(e,t)}),d.add(t)}};try{for(const e of t.payloads){if(!object(e))throw new Error("native terminal payload is not a typed reply");const t=terminalOutputItem(e);t&&a.push(t);for(const t of nativeOutputFileIds(e))await c(t)}for(const e of i)await c(e)}catch(e){if(!(e instanceof NativeArtifactDeliveryFailure))throw e;s=e,"completed"===o&&(o="failed")}const l=object(t.meta.agentMeta)?t.meta.agentMeta:{},p=terminalUsage(t);return{status:o,event:{type:"cancelled"===o?"response.failed":`response.${o}`,response:{id:e.responseId,status:o,output:a,..."string"==typeof l.model&&l.model.length>0?{model:l.model}:{},...p?{usage:p}:{},error:"failed"===o?{type:"harness_error",code:s?"artifact_delivery_failed":"harness_error",message:s?.message??(r.error||"The native harness could not complete this response.")}:null,incomplete_details:"incomplete"===o?{reason:"completed"===r.reason?"max_output_tokens":"runtime_interrupted"}:null}}}}export class StateCentralNativeStore{client;credential;titles;resolveOutputFile;writes=new Map;heads=new Map;publicEvents=new Map;memoryReads=new Map;executionObservations=new Map;constructor(e,t,n,i){this.client=e,this.credential=t,this.titles=n,this.resolveOutputFile=i}async recordGeneratedTitle(e,t){if(!this.titles)throw new Error("generated Session titles are unavailable");const n=generatedSessionName(t);if(!n)throw new Error("generated Session title is empty");return await this.titles.title(await this.credential(e),{context:e.context,session_id:e.sessionId,history_generation:e.historyGeneration,branch_id:e.branchId,name:n,idempotency_key:`title:${e.operationId}`})}withWrite(e,t){const n=key(e),i=(this.writes.get(n)??Promise.resolve()).then(t);return this.writes.set(n,i),i}async commitPublicProgress(e,t){await this.withWrite(e,async()=>{if(!this.publicEvents.get(operationKey(e))?.length)return;if(0!==(await t.list(e.sessionId)).length)throw new Error("native progress has unresolved original writes");const n=await this.load(e);if(n.terminal?.response_id===e.responseId)throw new Error("original native Response is already terminal");const i=structuredClone(this.publicEvents.get(operationKey(e))??[]),r=nativePayloadDigest(i),o=await this.prepareAppend({binding:e,events:[],expectedWatermark:n.watermark,publicProgress:!0,idempotencyKey:`progress:${e.operationId}:${n.watermark}:${r}`,nativeSnapshotDigest:r});await t.put(o);const a=await this.append(o);assertCentralNativeReceipt(o,a),await t.complete(o,a)})}recordPublicEvent(e,t){const n=operationKey(e),i=this.publicEvents.get(n)??[];i.push(structuredClone(t)),this.publicEvents.set(n,i)}recordMemoryRead(e,t){if("read"===t.status&&!t.watermark)throw new Error("actual Memory recall omitted its read watermark");this.memoryReads.set(operationKey(e),structuredClone(t))}bindExecutionObservation(e,t){if(t.admission.attemptId!==e.attemptId)throw new Error("native observation does not bind the original attempt");const n=operationKey(e),i=this.executionObservations.get(n);if(i&&!isDeepStrictEqual(i.source,t))throw new Error("native loaded observation changed");i||this.executionObservations.set(n,{source:structuredClone(t),loaded:!1})}nativeEventCapacity(e,t){const n=this.executionObservations.get(operationKey(e));return 200-(t?1:0)-(n&&!n.loaded?1:0)}async load(e){let t=null,n="0",i=null;const r=[];for(;;){const o=await this.client.load(await this.credential(e),{context:e.context,session_id:e.sessionId,history_generation:e.historyGeneration,branch_id:e.branchId,watermark:t,after:n,limit:200});this.assertPage(o,e,t,n),t=o.watermark;for(const e of o.events){if(e.sequence!==String(BigInt(n)+1n))throw new Error("central native event sequence has a gap");const t=decodeNativeChatEvent(e);if(isDeepStrictEqual(e.codec,codec))r.push(JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(t)));else if(!isDeepStrictEqual(e.codec,CENTRAL_RESPONSE_CONTROL_CODEC))throw new Error("central native event codec is not supported by this pinned Harness");n=e.sequence,i=e.event_id}if(o.next_after!==n||o.has_more&&BigInt(n)>=BigInt(t))throw new Error("central native page cursor does not match its fixed source");if(!o.has_more){if(n!==t)throw new Error("central native source ended before its fixed watermark");return this.heads.set(key(e),{watermark:t,lastEventId:i}),{codec:OPENCLAW_NATIVE_CODEC,events:r,watermark:t,writer:o.writer,terminal:o.terminal}}if(0===o.events.length)throw new Error("central native source made no page progress")}}async prepareAppend(e){if((e=structuredClone(e)).events.length>this.nativeEventCapacity(e.binding,Boolean(e.nativeOutcome)))throw new Error("native suffix must reserve its actual observation and terminal control rows");const t=this.heads.get(key(e.binding));if(!t||t.watermark!==e.expectedWatermark)throw new Error("native append has no exact loaded central source");let n=t.lastEventId;const i=e.events.map((t,i)=>{const r=Buffer.from(JSON.stringify(t),"utf8"),o=createHash("sha256").update(JSON.stringify([e.binding.sessionId,e.binding.historyGeneration,e.binding.branchId,String(BigInt(e.expectedWatermark)+BigInt(i)+1n)])).update(r).digest("hex"),a=encodeNativeChatEvent({eventId:`oc-${o}`,parentId:n,kind:t&&"object"==typeof t&&"type"in t&&"string"==typeof t.type?t.type:"native",codec:codec,content:r});return n=a.event_id,a});let r=null;const o=structuredClone(this.publicEvents.get(operationKey(e.binding))??[]),a=this.executionObservations.get(operationKey(e.binding)),s=(t,n,i)=>{const r=a.source,s="executed"===t?this.memoryReads.get(operationKey(e.binding)):void 0;o.push({type:executionObservationType,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,resolved_request_hash:r.resolvedRequestHash,payload:{phase:t,attempt:{...r.admission,...i?{nativeRunId:i.nativeRunId}:{}},read_watermark:r.readWatermark,source_ref:{id:n.event_id,digest:n.sha256},session_config_receipt:"loaded"===t?r.sessionConfigReceipt:null,runtime:null,partial_effective:{...r.loadedFacts,...i?.facts??{},...s?{memory_observation:s.status,memory_read_watermark:s.watermark}:{}}}})};if(a&&!a.loaded){const t=Buffer.from(JSON.stringify({type:"configuration.applied",...a.source}),"utf8"),r=`oc-loaded-${createHash("sha256").update(e.idempotencyKey).update(t).digest("hex")}`,o=encodeNativeChatEvent({eventId:r,parentId:n,kind:"configuration.applied",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:t});i.push(o),n=r,s("loaded",o)}if(e.publicProgress){if(e.nativeOutcome||0!==e.events.length||0===o.length)throw new Error("public native progress has invalid effect shape");const t=Buffer.from(JSON.stringify({type:"response.progress",response_id:e.binding.responseId,operation_id:e.binding.operationId,public_events_sha256:nativePayloadDigest(o)}),"utf8"),r=`oc-progress-${createHash("sha256").update(e.idempotencyKey).digest("hex")}`;i.push(encodeNativeChatEvent({eventId:r,parentId:n,kind:"response.progress",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:t})),n=r}if(e.nativeOutcome){const t=await terminalProjection(e.binding,e.nativeOutcome,this.resolveOutputFile,e.nativeOutputFileIds),d=`oc-terminal-${createHash("sha256").update(e.idempotencyKey).digest("hex")}`,c={type:"response.terminal",operation_id:e.binding.operationId,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,native_outcome:e.nativeOutcome},l=encodeNativeChatEvent({eventId:d,parentId:n,kind:"response.terminal",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:Buffer.from(JSON.stringify(c),"utf8")});i.push(l),r={response_id:e.binding.responseId,status:t.status,event_id:d};const p=a?executedFacts(e.nativeOutcome):void 0;p&&s("executed",l,p),o.push(t.event)}const d={context:e.binding.context,session_id:e.binding.sessionId,history_generation:e.binding.historyGeneration,branch_id:e.binding.branchId,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,public_events:o,writer:e.binding.writer,expected_watermark:e.expectedWatermark,operation_id:e.binding.operationId,idempotency_key:e.idempotencyKey,events:i,terminal:r},c=chatAppendDigest(d),l={...d,payload_sha256:c};return{...structuredClone(e),codec:OPENCLAW_NATIVE_CODEC,payloadDigest:c,wire:l}}async append(e){const t=e.wire;if(chatAppendDigest(t)!==e.payloadDigest||t.payload_sha256!==e.payloadDigest)throw new Error("pending native append no longer matches its original digest");const n=await this.client.append(await this.credential(e.binding),t);return this.accept(e.binding,t,n),n}async receipt(e){const t=e.binding;try{const n=await this.client.receipt(await this.credential(t),{context:t.context,session_id:t.sessionId,history_generation:t.historyGeneration,branch_id:t.branchId,idempotency_key:e.idempotencyKey,payload_sha256:e.payloadDigest});if(n.operation_id!==t.operationId||!isDeepStrictEqual(n.writer,t.writer))throw new Error("original native receipt belongs to another operation/writer");return n}catch(e){if(e instanceof ChatStoreHttpError&&404===e.status&&"not_found"===e.code)return null;throw e}}assertPage(e,t,n,i){if(e.session_id!==t.sessionId||e.history_generation!==t.historyGeneration||e.branch_id!==t.branchId||!decimal(e.watermark)||null!==n&&e.watermark!==n||BigInt(e.watermark)<BigInt(i)||!Array.isArray(e.events)||"boolean"!=typeof e.has_more||!isDeepStrictEqual(e.writer,t.writer))throw new Error("central native load does not match the authorized fixed source/writer")}accept(e,t,n){if(!(n.operation_id===e.operationId&&n.previous_watermark===t.expected_watermark&&decimal(n.read_watermark)&&n.read_watermark===String(BigInt(t.expected_watermark)+BigInt(t.events.length))&&isDeepStrictEqual(n.event_ids,t.events.map(e=>e.event_id))&&isDeepStrictEqual(n.terminal,t.terminal)&&isDeepStrictEqual(n.writer,e.writer)))throw new Error("native append returned a receipt for different committed content");const i=this.heads.get(key(e));this.heads.set(key(e),{watermark:n.read_watermark,lastEventId:n.event_ids.at(-1)??i?.lastEventId??null});const r=operationKey(e),o=this.executionObservations.get(r);o&&t.public_events.some(e=>e.type===executionObservationType&&object(e.payload)&&"loaded"===e.payload.phase)&&(o.loaded=!0);const a=this.publicEvents.get(r);if(a){const e=t.public_events.filter(e=>e.type!==executionObservationType),i=e.slice(0,e.length-(t.terminal?1:0));if(!isDeepStrictEqual(a.slice(0,i.length),i))throw new Error("confirmed public events differ from their pending native buffer");n.terminal||a.length===i.length?this.publicEvents.delete(r):this.publicEvents.set(r,a.slice(i.length))}}}
@@ -0,0 +1 @@
1
+ export const MODEL_PREPARATION_FAILED="model_preparation_failed";export const MODEL_PREPARATION_MESSAGE="The configured model could not be prepared. The task has not started.";export class ModelPreparationError extends Error{constructor(r){super(MODEL_PREPARATION_MESSAGE,{cause:r}),this.name="ModelPreparationError"}}export function readOpenClawConfig(r,o){try{const e="function"==typeof r?.config?.current?r.config.current():o;if(void 0===e)return;if(!e||"object"!=typeof e||Array.isArray(e))throw new Error("OpenClaw config is not an object");return e}catch(r){throw new ModelPreparationError(r)}}
@@ -1 +1 @@
1
- import{AROUTER_PROVIDER_ID}from"../media/arouter-config.js";let snapshot;export function setOpenClawConfigSnapshot(t){snapshot=t}function listedModelIds(t){if(!t||!Array.isArray(t.models))return[];const o=[];for(const e of t.models){if("string"==typeof e){const t=e.trim();t&&o.push(t);continue}if(e&&"string"==typeof e.id){const t=e.id.trim();t&&o.push(t)}}return o}function primaryProvider(t){const o=t?.agents?.defaults?.model?.primary;if("string"!=typeof o)return;const e=o.indexOf("/");return e>0?o.slice(0,e):void 0}export function createSessionModelRefs(t=snapshot){const o=t?.models?.providers??{},e=Object.keys(o).filter(t=>null!=o[t]),n=new Map;for(const t of e)for(const e of listedModelIds(o[t]))n.set(e,n.has(e)?void 0:t);const r=primaryProvider(t),s=r&&e.includes(r)?r:1===e.length?e[0]:AROUTER_PROVIDER_ID,i=e.includes(AROUTER_PROVIDER_ID)?e:[...e,AROUTER_PROVIDER_ID],f=t=>i.find(o=>t.startsWith(`${o}/`));return{toOpenClaw(t){return f(t)?t:`${o=t,n.get(o)??s}/${t}`;var o},toPlatform(t){const o=f(t);return o?t.slice(o.length+1):t}}}
1
+ import{ModelPreparationError}from"./openclaw-config.js";let snapshot;export function setOpenClawConfigSnapshot(r){snapshot=r}function listedModelIds(r){if(!r||!Array.isArray(r.models))return[];const o=[];for(const t of r.models){if("string"==typeof t){const r=t.trim();r&&o.push(r);continue}if(t&&"string"==typeof t.id){const r=t.id.trim();r&&o.push(r)}}return o}function primaryProvider(r){const o=r?.agents?.defaults?.model?.primary;if("string"!=typeof o)return;const t=o.indexOf("/");return t>0?o.slice(0,t):void 0}export function createSessionModelRefs(r=("function"==typeof snapshot?snapshot():snapshot)){const o=r?.models?.providers??{},t=Object.keys(o).filter(r=>null!=o[r]),e=new Map;for(const r of t)for(const t of listedModelIds(o[r]))e.set(t,e.has(t)?void 0:r);const n=primaryProvider(r),s=n??(1===t.length?t[0]:void 0),i=n?[...new Set([...t,n])]:t,d=r=>i.find(o=>r.startsWith(`${o}/`));return{toOpenClaw(r){const t=e.get(r);if(t)return`${t}/${r}`;if(e.has(r)){if(s&&listedModelIds(o[s]).includes(r))return`${s}/${r}`;throw new ModelPreparationError(new Error("Model provider is ambiguous"))}if(d(r))return r;if(!s)throw new ModelPreparationError(new Error("No configured model provider"));return`${s}/${r}`},toPlatform(r){const o=d(r);return o?r.slice(o.length+1):r}}}
@@ -1 +1 @@
1
- import{enableDeepseekReasoningStream}from"./deepseek-reasoning-stream.js";const DEFAULT_SURFACE="beeos-claw",DEFAULT_ORIGINATING_CHANNEL="webchat",DEFAULT_ORIGINATING_TARGET="main",DEFAULT_ORIGINATING_ACCOUNT_ID="main",isRecord=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),assertKnownReplyProtocol=e=>{if("acp"!==e&&"im"!==e)throw new Error(`unsupported reply route protocol=${e}`)},normalizeMediaUrls=e=>{if(!Array.isArray(e))return;const o=e.filter(e=>"string"==typeof e&&e.length>0);return o.length>0?o:void 0};export const hasRuntimeReplyApi=e=>"function"==typeof e?.channel?.reply?.dispatchReplyFromConfig;export const buildFinalizedMsgContext=(e,o)=>{assertKnownReplyProtocol(o.protocol);const t=o.originatingChannel??"beeos-claw",r=o.originatingChannel??"webchat",n=o.originatingTo??"main",i=o.accountId??"main",s=normalizeMediaUrls(e.attachments);return{Body:e.message,BodyForAgent:e.agentMessage,From:`${t}:${n}`,To:n,SessionKey:o.sessionId,Surface:t,Provider:t,OriginatingChannel:r,OriginatingTo:n,AccountId:i,CommandAuthorized:!0,...e.nativeSystemContext?{GroupSystemPrompt:e.nativeSystemContext}:{},...s?{MediaUrls:s}:{},...e.mediaPaths?.length?{MediaPaths:e.mediaPaths,MediaTypes:e.mediaTypes}:{}}};export const resolveReplySinkForRoute=(e,o)=>{assertKnownReplyProtocol(e.protocol);const t=o[e.protocol];if(!t)throw new Error(`runtime reply sink unavailable protocol=${e.protocol} requestId=${e.requestId}`);return t};const resolveRuntimeDispatchConfig=(e,o)=>{try{const o=e.config?.loadConfig?.();if(isRecord(o))return o}catch{}return o};export const dispatchRuntimeReplyWithRoute=async e=>{const o=e.runtime.channel?.reply?.dispatchReplyFromConfig;if("function"!=typeof o)throw new Error(`runtime reply API unavailable protocol=${e.replyRoute.protocol} requestId=${e.replyRoute.requestId}`);const t=resolveReplySinkForRoute(e.replyRoute,e.replySinks),r=enableDeepseekReasoningStream(resolveRuntimeDispatchConfig(e.runtime,e.pluginConfig)),n=o({ctx:buildFinalizedMsgContext(e.preparedPrompt,e.replyRoute),cfg:r,dispatcher:t.dispatcher,replyOptions:t.replyOptions});return e.onDispatchInvoked?.(n),n};
1
+ import{readOpenClawConfig,ModelPreparationError}from"./openclaw-config.js";import{enableDeepseekReasoningStream}from"./deepseek-reasoning-stream.js";const DEFAULT_SURFACE="beeos-claw",DEFAULT_ORIGINATING_CHANNEL="webchat",DEFAULT_ORIGINATING_TARGET="main",DEFAULT_ORIGINATING_ACCOUNT_ID="main",isRecord=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),assertKnownReplyProtocol=e=>{if("acp"!==e&&"im"!==e)throw new Error(`unsupported reply route protocol=${e}`)},normalizeMediaUrls=e=>{if(!Array.isArray(e))return;const o=e.filter(e=>"string"==typeof e&&e.length>0);return o.length>0?o:void 0};export const hasRuntimeReplyApi=e=>"function"==typeof e?.channel?.reply?.dispatchReplyFromConfig;export const buildFinalizedMsgContext=(e,o)=>{assertKnownReplyProtocol(o.protocol);const r=o.originatingChannel??"beeos-claw",t=o.originatingChannel??"webchat",n=o.originatingTo??"main",i=o.accountId??"main",a=normalizeMediaUrls(e.attachments);return{Body:e.message,BodyForAgent:e.agentMessage,From:`${r}:${n}`,To:n,SessionKey:o.sessionId,Surface:r,Provider:r,OriginatingChannel:t,OriginatingTo:n,AccountId:i,CommandAuthorized:!0,...e.nativeSystemContext?{GroupSystemPrompt:e.nativeSystemContext}:{},...a?{MediaUrls:a}:{},...e.mediaPaths?.length?{MediaPaths:e.mediaPaths,MediaTypes:e.mediaTypes}:{}}};export const resolveReplySinkForRoute=(e,o)=>{assertKnownReplyProtocol(e.protocol);const r=o[e.protocol];if(!r)throw new Error(`runtime reply sink unavailable protocol=${e.protocol} requestId=${e.requestId}`);return r};export const dispatchRuntimeReplyWithRoute=async e=>{const o=e.runtime.channel?.reply?.dispatchReplyFromConfig;if("function"!=typeof o)throw new Error(`runtime reply API unavailable protocol=${e.replyRoute.protocol} requestId=${e.replyRoute.requestId}`);const r=resolveReplySinkForRoute(e.replyRoute,e.replySinks),t=readOpenClawConfig(e.runtime);if(!t)throw new ModelPreparationError;const n=enableDeepseekReasoningStream(t),i=o({ctx:buildFinalizedMsgContext(e.preparedPrompt,e.replyRoute),cfg:n,dispatcher:r.dispatcher,replyOptions:r.replyOptions});return e.onDispatchInvoked?.(i),i};
@@ -1 +1 @@
1
- export const RUNTIME_ERROR_PART_KIND="runtime_error";const RUNTIME_ERROR_CODES=["insufficient_credits"];export function createRuntimeErrorPart(r){return{type:"custom",kind:"runtime_error",data:{code:r}}}export function parseRuntimeErrorPart(r){if(!r||"object"!=typeof r||Array.isArray(r))return;const t=r;if("custom"!==t.type||"runtime_error"!==t.kind)return;const e=t.data;if(!e||"object"!=typeof e||Array.isArray(e))return;const n=e.code;return"string"==typeof n&&RUNTIME_ERROR_CODES.includes(n)?createRuntimeErrorPart(n):void 0}
1
+ export const RUNTIME_ERROR_PART_KIND="runtime_error";const RUNTIME_ERROR_CODES=["insufficient_credits","model_preparation_failed"];export function createRuntimeErrorPart(r){return{type:"custom",kind:"runtime_error",data:{code:r}}}export function parseRuntimeErrorPart(r){if(!r||"object"!=typeof r||Array.isArray(r))return;const t=r;if("custom"!==t.type||"runtime_error"!==t.kind)return;const e=t.data;if(!e||"object"!=typeof e||Array.isArray(e))return;const o=e.code;return"string"==typeof o&&RUNTIME_ERROR_CODES.includes(o)?createRuntimeErrorPart(o):void 0}
@@ -1 +1 @@
1
- import{randomUUID}from"node:crypto";import{performance}from"node:perf_hooks";import{RuntimeCommandError}from"./runtime-command-dispatcher.js";import{ClearConversationUseCase}from"./conversation-clear-use-case.js";import{createSessionModelRefs}from"./openclaw-session-model.js";import{openClawSessionKeysFromList}from"./openclaw-session-key-resolution.js";async function modelSwitchTimingSpan(e,t,i){const s=performance.now();let n="succeeded";try{return await i()}catch(e){throw n="failed",e}finally{e&&process.stderr.write(`[MODEL_SWITCH_TIMING] component=runtime operationId=${e} stage=${t} outcome=${n} durationMs=${(performance.now()-s).toFixed(1)}\n`)}}export class RuntimeSessionControlService{clearRuntime;fallback;activeRuns;constructor(e,t,i){this.clearRuntime=e,this.fallback=t,this.activeRuns=i}async execute(e,t,i){const s=e;if("session.clear"===s.name){if(!i.historyBoundary)throw new RuntimeCommandError("INVALID_PARAMS",`${i.origin} clear attempt lacks its history boundary`);const e=s.context.conversation;return await new ClearConversationUseCase(i.historyBoundary,this.clearRuntime).execute({operationId:s.context.operationId,conversationId:e.runtimeConversationUid,runtimeSessionKey:e.runtimeSessionKey,runtimeEpoch:s.context.dispatchEpoch})}if("session.cancel"===s.name){if(!this.activeRuns)throw new RuntimeCommandError("INVALID_PARAMS","session.cancel active-run authority is not configured");const e=s;return await this.activeRuns.cancelExact({runtimeConversationUid:e.context.conversation.runtimeConversationUid,runtimeSessionKey:e.context.conversation.runtimeSessionKey,historyGeneration:e.context.historyGeneration,targetMessageId:e.params.targetMessageId}),{}}if(!this.fallback)throw new Error(`session command delegate is not configured: ${s.name}`);return await this.fallback.execute(s,t,i)}async projectCommitted(e,t,i){return await(this.fallback?.projectCommitted?.(e,t,i))}}export class OpenClawSessionMetadataService{metadata;constructor(e){this.metadata="function"==typeof e?new OpenClawGatewaySessionMetadataPort(e):e}async execute(e,t,i){const s=e,n=s.context.conversation.runtimeSessionKey,o={lease:t,attempt:i};switch(s.name){case"session.load":return await this.metadata.load(n,o);case"session.rename":{const e=s.params.title.slice(0,64);return await this.metadata.rename(n,e,o)}case"session.delete":return await this.metadata.delete(n,o);case"session.setMode":{const e=s.params.mode;return await this.metadata.setMode(n,e,o)}case"session.setModel":{const e=s.params.modelOverrideId;if(null!==e&&("string"!=typeof e||0===e.length||e.trim()!==e))throw new RuntimeCommandError("INVALID_PARAMS","modelOverrideId must be a non-empty string or null");const t=null===e?await modelSwitchTimingSpan(i.operationId,"resolve_agent_default_model",async()=>await this.metadata.resolveAgentDefaultModel(n,o)):void 0;if(null===e&&!t)throw new RuntimeCommandError("AGENT_DEFAULT_MODEL_NOT_CONFIGURED","agent default model is not configured");return await modelSwitchTimingSpan(i.operationId,"metadata_set_model",async()=>await this.metadata.setModel(n,e,t??void 0,o))}}throw new RuntimeCommandError("INVALID_PARAMS","unsupported session metadata command")}async projectCommitted(e,t,i){if("session.setModel"!==e.name)return;const s=e,n=t;if(this.metadata.projectCommittedSetModel&&await this.metadata.projectCommittedSetModel(s.context.conversation.runtimeSessionKey,n),"service"===i?.origin){if(!i.sessionModelProjection)throw new Error("Message Service session model projection is unavailable");return Object.freeze({state:"pending",revision:"0"})}if(!this.metadata.projectCommittedSetModel)throw new Error("session metadata projection is unavailable")}}export class OpenClawGatewaySessionMetadataPort{getGateway;projectModel;liveSessionKeys;modelMutations;constructor(e,t,i,s){this.getGateway=e,this.projectModel=t,this.liveSessionKeys=i,this.modelMutations=s}modelRefs(){return createSessionModelRefs()}async load(e,t){const i=await this.requireExistingOpenClawKey(e,t);return await this.gateway().request("sessions.resolve",{sessionKey:i}),{loaded:!0}}async rename(e,t,i){const s=await this.requireExistingOpenClawStoreKey(e,i);return await this.gateway().request("sessions.patch",{key:s,label:t}),{title:t}}async delete(e,t){const i=await this.requireExistingOpenClawStoreKey(e,t);return await this.gateway().request("sessions.delete",{key:i}),{deleted:!0}}async setMode(e,t,i){const s=openClawSessionModePatch(t),n=await this.requireExistingOpenClawStoreKey(e,i);if(!isAuthoritativeSetModeAck(await this.gateway().request("sessions.patch",{key:n,...s}),n,s))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact target and effective mode");return{mode:t}}async resolveAgentDefaultModel(e,t){const i=runtimeAgentId(this.liveSessionKeys?(await this.resolveSetModelKey(e,t)).key:await this.requireExistingOpenClawKey(e,t)),s=await this.gateway().request("agents.list",{}),n=s?.agents?.find(e=>e.id===i),o=n?.defaultModel??n?.model;if("string"!=typeof o||!o.trim()||o.trim()!==o)return null;const r=this.modelRefs().toPlatform(o),a=r.indexOf("/");return{modelId:r,...a>0?{modelProvider:r.slice(0,a)}:{}}}async setModel(e,t,i,s){const n=null===t?null:this.modelRefs().toOpenClaw(t),o=s?.attempt.operationId;let r=await modelSwitchTimingSpan(o,"resolve_set_model_key",async()=>await this.resolveSetModelKey(e,s));const a=await(this.modelMutations?.acquireInternal({sessionKey:r.key,label:"session model mutation"}));try{if(a){const t=await this.resolveSetModelKey(e,s);if(t.key!==a.sessionKey)throw new RuntimeCommandError("OUTCOME_UNKNOWN","model target changed while waiting for its physical session gate");r=t}const l=async()=>await modelSwitchTimingSpan(o,"openclaw_sessions_patch",async()=>await this.gateway().request("sessions.patch",{key:r.key,model:n,mustExist:!r.materialized}));let d;try{d=await l()}catch(t){if(r.materialized||!isMissingOpenClawStoreSession(t,r.key))throw t;r=await modelSwitchTimingSpan(o,"materialize_set_model_key",async()=>await this.materializeSetModelKey(e,r.key,s)),d=await l()}const{key:c,materialized:m}=r,u=resolveModelPatch(d,c,t,this.modelRefs()),h=u.effectiveModelId;if(null===t&&(!i||h!==i.modelId))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the prevalidated agent default");if(m){const e=await modelSwitchTimingSpan(o,"openclaw_sessions_list_post_materialize",async()=>await this.gateway().request("sessions.list",{includeDerivedTitles:!0}));if(!openClawSessionKeysFromList(e).has(c))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch acknowledged a model-intent session that is absent from the authoritative store");if(!this.liveSessionKeys?.registerMaterializedModelKey)throw new RuntimeCommandError("OUTCOME_UNKNOWN","model-intent session registration authority is unavailable");this.liveSessionKeys.registerMaterializedModelKey(c)}return u}finally{this.modelMutations?.releaseBeforeRuntime(a)}}async prepareNativeModel(e,t,i,s,n){await i();const o=void 0===t?null:this.modelRefs().toOpenClaw(t),r=void 0===s?void 0:openClawSessionModePatch(s),a=openClawPermissionModePatch(n),l=await this.gateway().request("sessions.patch",{key:e,model:o,...r,...a});await i();const d=l;if(!0!==d?.ok||d.key!==e)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native model patch did not acknowledge the exact qualified session");if(r&&!isAuthoritativeSetModeAck(l,e,r))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact target and effective mode");if(!isAuthoritativePermissionModeAck(l,a))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the effective permission mode");return resolveModelPatch(l,e,t??null,this.modelRefs())}async projectCommittedSetModel(e,t){if(!this.projectModel)throw new Error("session metadata projection is unavailable");const i=await this.requireExistingOpenClawKey(e);await this.projectModel(i,t)}async requireExistingOpenClawKey(e,t){if(await(this.liveSessionKeys?.waitForHydration?.()),!this.liveSessionKeys)return e;try{return this.liveSessionKeys.resolveLiveKey(e)}catch(i){if(!t||!isMissingLiveSession(i)||!this.liveSessionKeys.reconcileMissingLiveKey)throw i;return await this.liveSessionKeys.reconcileMissingLiveKey(e,t),this.liveSessionKeys.resolveLiveKey(e)}}async requireExistingOpenClawStoreKey(e,t){const i=await this.requireExistingOpenClawKey(e,t),s=await this.gateway().request("sessions.list",{includeDerivedTitles:!0});if(!openClawSessionKeysFromList(s).has(i))throw new RuntimeCommandError("INVALID_PARAMS",`OpenClaw session key does not exist (refusing sessions.patch upsert): ${i}`);return i}async resolveSetModelKey(e,t){let i;const s="service"===t?.attempt.origin&&void 0!==t.attempt.verifiedMessageGrant;try{i=await this.requireExistingOpenClawKey(e,t)}catch(e){if(!(s&&t&&isMissingLiveSession(e)&&this.liveSessionKeys?.materializeMissingModelKey&&this.liveSessionKeys.registerMaterializedModelKey))throw e}return i?{key:i,materialized:!1}:await this.materializeSetModelKey(e,void 0,t)}async materializeSetModelKey(e,t,i){if(!("service"===i?.attempt.origin&&void 0!==i.attempt.verifiedMessageGrant&&i&&this.liveSessionKeys?.materializeMissingModelKey&&this.liveSessionKeys.registerMaterializedModelKey)){throw new RuntimeCommandError("INVALID_PARAMS",`OpenClaw session key does not exist (refusing sessions.patch upsert): ${t??e}`)}const s=await this.liveSessionKeys.materializeMissingModelKey(e,i);if(t&&s!==t)throw new RuntimeCommandError("INVALID_PARAMS","verified model-intent key conflicts with the live local session");return{key:s,materialized:!0}}gateway(){const e=this.getGateway();if(!e?.isConnected)throw new RuntimeCommandError("GATEWAY_NOT_CONNECTED","Gateway not connected");return e}}function isMissingLiveSession(e){return e instanceof RuntimeCommandError&&"INVALID_PARAMS"===e.code&&e.message.startsWith("no live local session")}function isMissingOpenClawStoreSession(e,t){return e instanceof Error&&e.message===`No session found: ${t}`}function resolveModelPatch(e,t,i,s){const n=null===i?null:s.toOpenClaw(i);if(!isAuthoritativeSetModelAck(e,t,n,i))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact existing session and effective model");const o=e.resolved.model,r=s.toPlatform(o);if(null!==i&&r!==i&&o!==n)throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the requested override");return{...null===i?{}:{modelOverrideId:i},effectiveModelId:r,...e.resolved.modelProvider?{modelProvider:e.resolved.modelProvider}:{}}}function runtimeAgentId(e){const t=e.split(":");return"agent"===t[0]&&t[1]?.trim()?t[1]:"main"}export function openClawSessionModePatch(e){const t="verbose"===e||"detailed"===e?{verboseLevel:"full"}:"reasoning"===e||"thinking"===e?{reasoningLevel:"stream"}:"concise"===e||"default"===e?{verboseLevel:"default"}:null;if(!t)throw new RuntimeCommandError("INVALID_PARAMS",`unsupported session mode: ${e}`);return t}export function openClawPermissionModePatch(e){return{permissionMode:"full"===e?"full":null}}function isAuthoritativePermissionModeAck(e,t){const i=e?.entry;return!(!i||"object"!=typeof i||Array.isArray(i))&&i.permissionMode===(t.permissionMode??void 0)}function isAuthoritativeSetModeAck(e,t,i){if(!e||"object"!=typeof e||Array.isArray(e))return!1;const s=e;if(!0!==s.ok||s.key!==t||!s.entry||"object"!=typeof s.entry||Array.isArray(s.entry))return!1;const n=s.entry;return"verboseLevel"in i?n.verboseLevel===i.verboseLevel:n.reasoningLevel===i.reasoningLevel}function isAuthoritativeSetModelAck(e,t,i,s){if(!e||"object"!=typeof e||Array.isArray(e))return!1;const n=e;if("ok"in n&&!0!==n.ok)return!1;if("key"in n&&n.key!==t)return!1;const o=n.resolved;if(!o||"object"!=typeof o||Array.isArray(o))return!1;const r=o.model;return"string"==typeof r&&0!==r.length&&r.trim()===r&&(null!==s||null===i)}export class LocalConversationHistoryBoundary{onCommit;kind="local";intents=new Map;convergence=new Map;generations=new Map;constructor(e){this.onCommit=e}currentGeneration(e){return String(this.generations.get(e)??0n)}async prepare(e){const t=this.intents.get(e.operationId);if(t)return t;const i=(new Date).toISOString(),s=this.generations.get(e.conversationId)??0n,n={intentId:randomUUID(),operationId:e.operationId,conversationId:e.conversationId,state:"prepared",runtimeEpoch:e.runtimeEpoch,fromGeneration:String(s),toGeneration:String(s+1n),boundaryOffset:"0",version:"1",createdAt:i,updatedAt:i};return this.intents.set(e.operationId,n),n}async markResetting(e,t){return this.assertState(e,"prepared"),this.convergence.set(e.operationId,t),this.transition(e,"resetting")}async loadRunConvergence(e){const t=this.convergence.get(e.operationId);if(!t)throw new Error("local clear convergence receipt missing");return t}async markResetDone(e){return this.assertState(e,"resetting"),this.transition(e,"reset_done")}async commit(e){return this.assertState(e,"reset_done"),await(this.onCommit?.(e.conversationId)),this.generations.set(e.conversationId,BigInt(e.toGeneration)),this.transition(e,"committed")}async abortPrepared(e){this.assertState(e,"prepared"),this.transition(e,"aborted")}transition(e,t){const i={...e,state:t,version:String(BigInt(e.version)+1n),updatedAt:(new Date).toISOString()};return this.intents.set(e.operationId,i),i}assertState(e,t){const i=this.intents.get(e.operationId);if(!i||i.version!==e.version||i.state!==t)throw new Error(`local clear transition fenced: expected ${t}`)}}
1
+ import{ModelPreparationError}from"./openclaw-config.js";import{randomUUID}from"node:crypto";import{performance}from"node:perf_hooks";import{RuntimeCommandError}from"./runtime-command-dispatcher.js";import{ClearConversationUseCase}from"./conversation-clear-use-case.js";import{createSessionModelRefs}from"./openclaw-session-model.js";import{openClawSessionKeysFromList}from"./openclaw-session-key-resolution.js";async function modelSwitchTimingSpan(e,t,i){const s=performance.now();let n="succeeded";try{return await i()}catch(e){throw n="failed",e}finally{e&&process.stderr.write(`[MODEL_SWITCH_TIMING] component=runtime operationId=${e} stage=${t} outcome=${n} durationMs=${(performance.now()-s).toFixed(1)}\n`)}}export class RuntimeSessionControlService{clearRuntime;fallback;activeRuns;constructor(e,t,i){this.clearRuntime=e,this.fallback=t,this.activeRuns=i}async execute(e,t,i){const s=e;if("session.clear"===s.name){if(!i.historyBoundary)throw new RuntimeCommandError("INVALID_PARAMS",`${i.origin} clear attempt lacks its history boundary`);const e=s.context.conversation;return await new ClearConversationUseCase(i.historyBoundary,this.clearRuntime).execute({operationId:s.context.operationId,conversationId:e.runtimeConversationUid,runtimeSessionKey:e.runtimeSessionKey,runtimeEpoch:s.context.dispatchEpoch})}if("session.cancel"===s.name){if(!this.activeRuns)throw new RuntimeCommandError("INVALID_PARAMS","session.cancel active-run authority is not configured");const e=s;return await this.activeRuns.cancelExact({runtimeConversationUid:e.context.conversation.runtimeConversationUid,runtimeSessionKey:e.context.conversation.runtimeSessionKey,historyGeneration:e.context.historyGeneration,targetMessageId:e.params.targetMessageId}),{}}if(!this.fallback)throw new Error(`session command delegate is not configured: ${s.name}`);return await this.fallback.execute(s,t,i)}async projectCommitted(e,t,i){return await(this.fallback?.projectCommitted?.(e,t,i))}}export class OpenClawSessionMetadataService{metadata;constructor(e){this.metadata="function"==typeof e?new OpenClawGatewaySessionMetadataPort(e):e}async execute(e,t,i){const s=e,n=s.context.conversation.runtimeSessionKey,o={lease:t,attempt:i};switch(s.name){case"session.load":return await this.metadata.load(n,o);case"session.rename":{const e=s.params.title.slice(0,64);return await this.metadata.rename(n,e,o)}case"session.delete":return await this.metadata.delete(n,o);case"session.setMode":{const e=s.params.mode;return await this.metadata.setMode(n,e,o)}case"session.setModel":{const e=s.params.modelOverrideId;if(null!==e&&("string"!=typeof e||0===e.length||e.trim()!==e))throw new RuntimeCommandError("INVALID_PARAMS","modelOverrideId must be a non-empty string or null");const t=null===e?await modelSwitchTimingSpan(i.operationId,"resolve_agent_default_model",async()=>await this.metadata.resolveAgentDefaultModel(n,o)):void 0;if(null===e&&!t)throw new RuntimeCommandError("AGENT_DEFAULT_MODEL_NOT_CONFIGURED","agent default model is not configured");return await modelSwitchTimingSpan(i.operationId,"metadata_set_model",async()=>await this.metadata.setModel(n,e,t??void 0,o))}}throw new RuntimeCommandError("INVALID_PARAMS","unsupported session metadata command")}async projectCommitted(e,t,i){if("session.setModel"!==e.name)return;const s=e,n=t;if(this.metadata.projectCommittedSetModel&&await this.metadata.projectCommittedSetModel(s.context.conversation.runtimeSessionKey,n),"service"===i?.origin){if(!i.sessionModelProjection)throw new Error("Message Service session model projection is unavailable");return Object.freeze({state:"pending",revision:"0"})}if(!this.metadata.projectCommittedSetModel)throw new Error("session metadata projection is unavailable")}}export class OpenClawGatewaySessionMetadataPort{getGateway;projectModel;liveSessionKeys;modelMutations;constructor(e,t,i,s){this.getGateway=e,this.projectModel=t,this.liveSessionKeys=i,this.modelMutations=s}modelRefs(){return createSessionModelRefs()}async load(e,t){const i=await this.requireExistingOpenClawKey(e,t);return await this.gateway().request("sessions.resolve",{sessionKey:i}),{loaded:!0}}async rename(e,t,i){const s=await this.requireExistingOpenClawStoreKey(e,i);return await this.gateway().request("sessions.patch",{key:s,label:t}),{title:t}}async delete(e,t){const i=await this.requireExistingOpenClawStoreKey(e,t);return await this.gateway().request("sessions.delete",{key:i}),{deleted:!0}}async setMode(e,t,i){const s=openClawSessionModePatch(t),n=await this.requireExistingOpenClawStoreKey(e,i);if(!isAuthoritativeSetModeAck(await this.gateway().request("sessions.patch",{key:n,...s}),n,s))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact target and effective mode");return{mode:t}}async resolveAgentDefaultModel(e,t){const i=runtimeAgentId(this.liveSessionKeys?(await this.resolveSetModelKey(e,t)).key:await this.requireExistingOpenClawKey(e,t)),s=await this.gateway().request("agents.list",{}),n=s?.agents?.find(e=>e.id===i),o=n?.defaultModel??n?.model;if("string"!=typeof o||!o.trim()||o.trim()!==o)return null;const r=this.modelRefs().toPlatform(o),a=r.indexOf("/");return{modelId:r,...a>0?{modelProvider:r.slice(0,a)}:{}}}async setModel(e,t,i,s){const n=null===t?null:this.modelRefs().toOpenClaw(t),o=s?.attempt.operationId;let r=await modelSwitchTimingSpan(o,"resolve_set_model_key",async()=>await this.resolveSetModelKey(e,s));const a=await(this.modelMutations?.acquireInternal({sessionKey:r.key,label:"session model mutation"}));try{if(a){const t=await this.resolveSetModelKey(e,s);if(t.key!==a.sessionKey)throw new RuntimeCommandError("OUTCOME_UNKNOWN","model target changed while waiting for its physical session gate");r=t}const l=async()=>await modelSwitchTimingSpan(o,"openclaw_sessions_patch",async()=>await this.gateway().request("sessions.patch",{key:r.key,model:n,mustExist:!r.materialized}));let d;try{d=await l()}catch(t){if(r.materialized||!isMissingOpenClawStoreSession(t,r.key))throw t;r=await modelSwitchTimingSpan(o,"materialize_set_model_key",async()=>await this.materializeSetModelKey(e,r.key,s)),d=await l()}const{key:c,materialized:m}=r,u=resolveModelPatch(d,c,t,this.modelRefs()),h=u.effectiveModelId;if(null===t&&(!i||h!==i.modelId))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the prevalidated agent default");if(m){const e=await modelSwitchTimingSpan(o,"openclaw_sessions_list_post_materialize",async()=>await this.gateway().request("sessions.list",{includeDerivedTitles:!0}));if(!openClawSessionKeysFromList(e).has(c))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch acknowledged a model-intent session that is absent from the authoritative store");if(!this.liveSessionKeys?.registerMaterializedModelKey)throw new RuntimeCommandError("OUTCOME_UNKNOWN","model-intent session registration authority is unavailable");this.liveSessionKeys.registerMaterializedModelKey(c)}return u}finally{this.modelMutations?.releaseBeforeRuntime(a)}}async prepareNativeModel(e,t,i,s,n){await i();const o=void 0===t?null:this.modelRefs().toOpenClaw(t),r=void 0===s?void 0:openClawSessionModePatch(s),a=openClawPermissionModePatch(n);let l;try{l=await this.gateway().request("sessions.patch",{key:e,model:o,...r,...a})}catch(e){if(e instanceof RuntimeCommandError)throw e;throw new ModelPreparationError(e)}await i();const d=l;if(!0!==d?.ok||d.key!==e)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native model patch did not acknowledge the exact qualified session");if(r&&!isAuthoritativeSetModeAck(l,e,r))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact target and effective mode");if(!isAuthoritativePermissionModeAck(l,a))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the effective permission mode");return resolveModelPatch(l,e,t??null,this.modelRefs())}async projectCommittedSetModel(e,t){if(!this.projectModel)throw new Error("session metadata projection is unavailable");const i=await this.requireExistingOpenClawKey(e);await this.projectModel(i,t)}async requireExistingOpenClawKey(e,t){if(await(this.liveSessionKeys?.waitForHydration?.()),!this.liveSessionKeys)return e;try{return this.liveSessionKeys.resolveLiveKey(e)}catch(i){if(!t||!isMissingLiveSession(i)||!this.liveSessionKeys.reconcileMissingLiveKey)throw i;return await this.liveSessionKeys.reconcileMissingLiveKey(e,t),this.liveSessionKeys.resolveLiveKey(e)}}async requireExistingOpenClawStoreKey(e,t){const i=await this.requireExistingOpenClawKey(e,t),s=await this.gateway().request("sessions.list",{includeDerivedTitles:!0});if(!openClawSessionKeysFromList(s).has(i))throw new RuntimeCommandError("INVALID_PARAMS",`OpenClaw session key does not exist (refusing sessions.patch upsert): ${i}`);return i}async resolveSetModelKey(e,t){let i;const s="service"===t?.attempt.origin&&void 0!==t.attempt.verifiedMessageGrant;try{i=await this.requireExistingOpenClawKey(e,t)}catch(e){if(!(s&&t&&isMissingLiveSession(e)&&this.liveSessionKeys?.materializeMissingModelKey&&this.liveSessionKeys.registerMaterializedModelKey))throw e}return i?{key:i,materialized:!1}:await this.materializeSetModelKey(e,void 0,t)}async materializeSetModelKey(e,t,i){if(!("service"===i?.attempt.origin&&void 0!==i.attempt.verifiedMessageGrant&&i&&this.liveSessionKeys?.materializeMissingModelKey&&this.liveSessionKeys.registerMaterializedModelKey)){throw new RuntimeCommandError("INVALID_PARAMS",`OpenClaw session key does not exist (refusing sessions.patch upsert): ${t??e}`)}const s=await this.liveSessionKeys.materializeMissingModelKey(e,i);if(t&&s!==t)throw new RuntimeCommandError("INVALID_PARAMS","verified model-intent key conflicts with the live local session");return{key:s,materialized:!0}}gateway(){const e=this.getGateway();if(!e?.isConnected)throw new RuntimeCommandError("GATEWAY_NOT_CONNECTED","Gateway not connected");return e}}function isMissingLiveSession(e){return e instanceof RuntimeCommandError&&"INVALID_PARAMS"===e.code&&e.message.startsWith("no live local session")}function isMissingOpenClawStoreSession(e,t){return e instanceof Error&&e.message===`No session found: ${t}`}function resolveModelPatch(e,t,i,s){const n=null===i?null:s.toOpenClaw(i);if(!isAuthoritativeSetModelAck(e,t,n,i))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact existing session and effective model");const o=e.resolved.model,r=s.toPlatform(o);if(null!==i&&r!==i&&o!==n)throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the requested override");return{...null===i?{}:{modelOverrideId:i},effectiveModelId:r,...e.resolved.modelProvider?{modelProvider:e.resolved.modelProvider}:{}}}function runtimeAgentId(e){const t=e.split(":");return"agent"===t[0]&&t[1]?.trim()?t[1]:"main"}export function openClawSessionModePatch(e){const t="verbose"===e||"detailed"===e?{verboseLevel:"full"}:"reasoning"===e||"thinking"===e?{reasoningLevel:"stream"}:"concise"===e||"default"===e?{verboseLevel:"default"}:null;if(!t)throw new RuntimeCommandError("INVALID_PARAMS",`unsupported session mode: ${e}`);return t}export function openClawPermissionModePatch(e){return{permissionMode:"full"===e?"full":null}}function isAuthoritativePermissionModeAck(e,t){const i=e?.entry;return!(!i||"object"!=typeof i||Array.isArray(i))&&i.permissionMode===(t.permissionMode??void 0)}function isAuthoritativeSetModeAck(e,t,i){if(!e||"object"!=typeof e||Array.isArray(e))return!1;const s=e;if(!0!==s.ok||s.key!==t||!s.entry||"object"!=typeof s.entry||Array.isArray(s.entry))return!1;const n=s.entry;return"verboseLevel"in i?n.verboseLevel===i.verboseLevel:n.reasoningLevel===i.reasoningLevel}function isAuthoritativeSetModelAck(e,t,i,s){if(!e||"object"!=typeof e||Array.isArray(e))return!1;const n=e;if("ok"in n&&!0!==n.ok)return!1;if("key"in n&&n.key!==t)return!1;const o=n.resolved;if(!o||"object"!=typeof o||Array.isArray(o))return!1;const r=o.model;return"string"==typeof r&&0!==r.length&&r.trim()===r&&(null!==s||null===i)}export class LocalConversationHistoryBoundary{onCommit;kind="local";intents=new Map;convergence=new Map;generations=new Map;constructor(e){this.onCommit=e}currentGeneration(e){return String(this.generations.get(e)??0n)}async prepare(e){const t=this.intents.get(e.operationId);if(t)return t;const i=(new Date).toISOString(),s=this.generations.get(e.conversationId)??0n,n={intentId:randomUUID(),operationId:e.operationId,conversationId:e.conversationId,state:"prepared",runtimeEpoch:e.runtimeEpoch,fromGeneration:String(s),toGeneration:String(s+1n),boundaryOffset:"0",version:"1",createdAt:i,updatedAt:i};return this.intents.set(e.operationId,n),n}async markResetting(e,t){return this.assertState(e,"prepared"),this.convergence.set(e.operationId,t),this.transition(e,"resetting")}async loadRunConvergence(e){const t=this.convergence.get(e.operationId);if(!t)throw new Error("local clear convergence receipt missing");return t}async markResetDone(e){return this.assertState(e,"resetting"),this.transition(e,"reset_done")}async commit(e){return this.assertState(e,"reset_done"),await(this.onCommit?.(e.conversationId)),this.generations.set(e.conversationId,BigInt(e.toGeneration)),this.transition(e,"committed")}async abortPrepared(e){this.assertState(e,"prepared"),this.transition(e,"aborted")}transition(e,t){const i={...e,state:t,version:String(BigInt(e.version)+1n),updatedAt:(new Date).toISOString()};return this.intents.set(e.operationId,i),i}assertState(e,t){const i=this.intents.get(e.operationId);if(!i||i.version!==e.version||i.state!==t)throw new Error(`local clear transition fenced: expected ${t}`)}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beeos-claw",
3
- "version": "0.6.96",
3
+ "version": "0.6.97",
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>",
@@ -93,5 +93,5 @@
93
93
  "zod": "4.6.7",
94
94
  "qs": "6.16.1"
95
95
  },
96
- "gitHead": "bd6b67b59ecf8110733d116b6221110088733fbd"
96
+ "gitHead": "b756df64b68b385149d4a3e66d27671549900f94"
97
97
  }