beeos-claw 0.6.63-staging.6 → 0.6.63-staging.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import{createHash,randomUUID}from"node:crypto";import{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{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},_=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)}`)}},y=promptRunKey(t.channelId,t.inboundMessageId),R=t.sessionKey??"agent:main",E=new AbortController;let w,f,b,v,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 O;const k=()=>{void 0!==O&&(clearTimeout(O),O=void 0)},L=async e=>{if($??=e,E.abort(e),!w)return{ok:!0};const n=await l.requestCancel(w,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(y,{requestId:m,channelId:t.channelId,requestCancel:L,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 A=e.retainedStream?.id??deterministicReplyMessageId("asst",t.channelId,t.inboundMessageId,t.selfPrincipalId),T={conversationId:t.channelId,clientMessageId:A,idempotencyKey:A,replyTo:e.inReplyTo??t.inboundMessageId,requestId:m,type:"agent_reply",content:{}},D=e.retainedStream??r.messages.startStream(T);let U,F=!1;try{const e=await D.opened();F="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,A)).state}catch{}return a.warn?.(`[im] runtime reply stream open outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} reply_id=${A} 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(y),!1}if(F)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(y),!1;const K=()=>{L(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 P=new SerializedCallbackQueue,Q=createImReplySink({stream:D,abortSignal:E.signal,callbackQueue:P,...e.onNativeRunCompletion?{onCallbackFailure:e=>P.fail(e)}:{},logger:a,requestId:m,startedAtMs:I,runId:p,channelId:t.channelId,inboundMessageId:t.inboundMessageId,origin:g,sessionKey:R,onAgentRunStart:e=>{l.bindRun(w,e),void 0!==U&&logChatLatency(a,"claw.runtime.pre_run_completed",m,U)}}),Y=interceptAgentRuntimeFailures(Q,"im_runtime",e=>a.warn?.(`[im] runtime failure reply suppressed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} error_code=${e.errorCode}`)),G=Y.sink;let j=!1;const V=async n=>{e.onNativeRunCompletion||G.dispatcher.markComplete(n);try{e.onNativeRunCompletion&&G.dispatcher.markComplete(n),await G.dispatcher.waitForIdle()}catch(n){if(e.onNativeRunCompletion)throw P.fail(n),n}},x=()=>{if(e.onNativeRunCompletion)return;k();const n=normalizePositiveTimeoutMs(e.abortTerminalGraceMs)??1e4;O=setTimeout(()=>{O=void 0,(async()=>{if(D.isTerminated)return;const e=E.signal.reason??$,n="string"==typeof e&&e.startsWith("chat_cancel");if(await V("failure"),!D.isTerminated)try{n?await D.cancel({stopReason:"user_stop"}):await failMessageStream(D,{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?x():E.signal.addEventListener("abort",x,{once:!0});const B=()=>{if(!E.signal.aborted)return;const e=E.signal.reason;throw e instanceof Error?e:new Error(String(e??"runtime dispatch aborted"))};let z,W,J,H,X,Z;const ee=async e=>{if(!w)throw new Error("session_mutation_not_acquired");const n=await l.converge(w,e);return n.ok?(z=n.permit,!0):(a.error?.(`[im] session mutation recovery required requestId=${m} sessionKey=${R} reason=${n.recovery.reason}`),W={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)};try{if(B(),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(D,{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(w=d.token,logChatLatency(a,"claw.session_gate.acquired",m,I),l.bindRun(w,p),H=o.register(R,Q),X=s.register(R,Q),Z=c.register(p,{requestId:m,startedAtMs:I,logger:a}),u){const n=l.snapshot(R);J=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(J,async()=>{const e=`chat_cancel:activeRun:${J.activeRunRegistrationId}`,n=await i.abort(y,e);return n.ok||"already_aborted"===n.reason?"accepted":"terminal_committing"===n.reason||"not_found"===n.reason?"already_terminal":"recovery_required"})}B(),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(),B()),e.onNativeRunCompletion&&e.prepareNativeModel&&(await e.prepareNativeModel(w),B(),await(e.assertNativeTarget?.()),B()),U=Date.now(),logChatLatency(a,"claw.runtime.invoke",m,I);const E=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);E.unref?.();const S=dispatchRuntimeReplyWithRoute({runtime:n,pluginConfig:e.pluginConfig,preparedPrompt:t.dispatchInput,replyRoute:h,replySinks:{im:G},onDispatchInvoked:n=>{if(j=!0,e.onNativeRunCompletion){f=n;const t=new Promise((e,n)=>{v=e,M=n});t.catch(()=>{}),e.onNativeRunCompletion({runtimeRunId:p,token:w,hostCompletion:n,completion:t})}logChatLatency(a,"claw.runtime.dispatch_returned",m,U)}}),$=e.onNativeRunCompletion?await S:await Promise.race([S,q]).finally(()=>{});e.onNativeRunCompletion&&(await f,await b);const C=Y.detectedFailure();if(C)throw new Error(C.diagnosticMessage);if(B(),await V("success"),e.onNativeRunCompletion&&await b,B(),!i.claimTerminal(y,"completion")){if(B(),"cancelling"===i.phase(y))throw new Error("cancellation in progress");throw new Error("terminal outcome already claimed")}if(!await ee("completed"))return await failMessageStream(D,{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",...W?{recovery:W}:{}}),!1;const N=G.dispatcher.getTerminalErrorText?.();if(void 0!==N){let n=!1;const r=classifyAgentRuntimeFailure({raw:N,source:"im_runtime",runtimeKind:"openclaw"});try{await writeRuntimeFailure(D,{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&&J&&u.activeRuns.markTerminal(J,"failed"),a.warn?.(`[im] runtime dispatch ended with an error terminal requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} counts=${JSON.stringify($.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 _("",N),!1}let O=!1;try{await D.finalize({stopReason:"end_turn"})}catch(e){O=!0,a.warn?.(`[im] runtime reply stream finalize outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}u&&J&&u.activeRuns.markTerminal(J,"completed");const k={...$.counts,source:Q.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:O?"outcome_unknown":"completed",tool_count:k.tool}),e.onLifecycleEvent?.({type:"dispatch_complete",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,counts:k,...O?{terminalWriteFailed:!0}:{}});const L=G.dispatcher.getAccumulatedBody?.()??"";O||await _(L,"");const A="string"==typeof t.dispatchInput.message?t.dispatchInput.message:"";return maybeRenameImConversationTitle({client:r,conversationId:t.channelId,question:A,answer:L,logger:a}),!0}catch(n){S=n,e.onNativeRunCompletion&&(await(f?.then(()=>{},()=>{})),await b),await V("failure"),e.onNativeRunCompletion&&await b;const r=E.signal.aborted,o=r?E.signal.reason:void 0,s="cancelling"===i.phase(y),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(y,p)){if(a.warn?.(`[im] terminal claim raced requestId=${m} channel=${t.channelId}; best-effort envelope terminal if still streaming`),!D.isTerminated)try{l?await D.cancel({stopReason:"user_stop"}):await failMessageStream(D,{body:formatErrMessage(n),stopReason:"error"})}catch(e){a.warn?.(`[im] raced terminal write failed requestId=${m}: ${formatErrMessage(e)}`)}throw n}const g=l?"cancelled":"error";if(u&&J&&!e.onNativeRunCompletion&&u.activeRuns.markTerminal(J,"cancelled"===g?"cancelled":"failed"),w&&!await ee(g)){if(e.onNativeRunCompletion)throw new Error(SESSION_RECOVERY_REQUIRED_CODE);throw l?await D.cancel({stopReason:"user_stop"}).catch(()=>{}):await failMessageStream(D,{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:d,...W?{recovery:W}:{}}),n}u&&J&&e.onNativeRunCompletion&&u.activeRuns.markTerminal(J,"cancelled"===g?"cancelled":"failed");const h=classifyAgentRuntimeFailure({raw:n,source:"im_runtime",runtimeKind:"openclaw",requestAborted:l}),R=l?h:Y.detectedFailure()??h;let v=!1;try{l?await D.cancel({stopReason:"user_stop"}):await writeRuntimeFailure(D,{body:R.publicMessage,stopReason:messageStopReasonForRuntimeFailure(R),businessErrorCode:R.businessErrorCode})}catch(e){v=!0,a.warn?.(`[im] runtime stream terminal write failed requestId=${m} channel=${t.channelId}: ${formatErrMessage(e)}`)}throw a.warn?.(`[im] runtime dispatch failed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} cause=${d} dispatchInvoked=${j} 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||v||await _("",R.publicMessage),n}finally{e.onNativeRunCompletion&&(z?v?.(z):(j&&w&&l.requireRecovery(w,"terminal_not_observed"),M?.(S??new Error(SESSION_RECOVERY_REQUIRED_CODE)))),e.abortSignal?.removeEventListener("abort",K),k(),Z?.(),X?.(),H?.(),i.unregister(y),j?z&&l.release(z):l.releaseBeforeRuntime(w)}};
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{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},_=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)}`)}},y=promptRunKey(t.channelId,t.inboundMessageId),R=t.sessionKey??"agent:main",E=new AbortController;let w,f,b,v,M,S,$,C;const N=new Promise((e,n)=>{C=n});e.onNativeRunCompletion&&N.catch(()=>{});const q=e.onNativeRunCompletion?{chatAbort:(e,n)=>(b=Promise.resolve().then(()=>d.chatAbort(e,n)),b)}:d;let O;const k=()=>{void 0!==O&&(clearTimeout(O),O=void 0)},L=async e=>{if($??=e,E.abort(e),!w)return{ok:!0};const n=await l.requestCancel(w,q);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(y,{requestId:m,channelId:t.channelId,requestCancel:L,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 A=e.retainedStream?.id??deterministicReplyMessageId("asst",t.channelId,t.inboundMessageId,t.selfPrincipalId),T={conversationId:t.channelId,clientMessageId:A,idempotencyKey:A,replyTo:e.inReplyTo??t.inboundMessageId,requestId:m,type:"agent_reply",content:{}},D=e.retainedStream??r.messages.startStream(T);let U,F=!1;try{const e=await D.opened();F="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,A)).state}catch{}return a.warn?.(`[im] runtime reply stream open outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} reply_id=${A} 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(y),!1}if(F)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(y),!1;const K=()=>{L(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 P=new SerializedCallbackQueue,Q=createImReplySink({stream:D,persistObservedToolResults:void 0!==e.retainedStream,abortSignal:E.signal,callbackQueue:P,...e.onNativeRunCompletion?{onCallbackFailure:e=>P.fail(e)}:{},logger:a,requestId:m,startedAtMs:I,runId:p,channelId:t.channelId,inboundMessageId:t.inboundMessageId,origin:g,sessionKey:R,onAgentRunStart:n=>{l.bindRun(w,n),e.onNativeAgentRunStart?.(n),void 0!==U&&logChatLatency(a,"claw.runtime.pre_run_completed",m,U)}}),Y=interceptAgentRuntimeFailures(Q,"im_runtime",e=>a.warn?.(`[im] runtime failure reply suppressed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} error_code=${e.errorCode}`)),G=Y.sink;let j=!1;const V=async n=>{e.onNativeRunCompletion||G.dispatcher.markComplete(n);try{e.onNativeRunCompletion&&G.dispatcher.markComplete(n),await G.dispatcher.waitForIdle()}catch(n){if(e.onNativeRunCompletion)throw P.fail(n),n}},x=()=>{if(e.onNativeRunCompletion)return;k();const n=normalizePositiveTimeoutMs(e.abortTerminalGraceMs)??1e4;O=setTimeout(()=>{O=void 0,(async()=>{if(D.isTerminated)return;const e=E.signal.reason??$,n="string"==typeof e&&e.startsWith("chat_cancel");if(await V("failure"),!D.isTerminated)try{n?await D.cancel({stopReason:"user_stop"}):await failMessageStream(D,{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?x():E.signal.addEventListener("abort",x,{once:!0});const B=()=>{if(!E.signal.aborted)return;const e=E.signal.reason;throw e instanceof Error?e:new Error(String(e??"runtime dispatch aborted"))};let z,W,J,H,X,Z;const ee=async e=>{if(!w)throw new Error("session_mutation_not_acquired");const n=await l.converge(w,e);return n.ok?(z=n.permit,!0):(a.error?.(`[im] session mutation recovery required requestId=${m} sessionKey=${R} reason=${n.recovery.reason}`),W={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)};try{if(B(),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(D,{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(w=d.token,logChatLatency(a,"claw.session_gate.acquired",m,I),l.bindRun(w,p),H=o.register(R,Q),X=s.register(R,Q),Z=c.register(p,{requestId:m,startedAtMs:I,logger:a}),u){const n=l.snapshot(R);J=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(J,async()=>{const e=`chat_cancel:activeRun:${J.activeRunRegistrationId}`,n=await i.abort(y,e);return n.ok||"already_aborted"===n.reason?"accepted":"terminal_committing"===n.reason||"not_found"===n.reason?"already_terminal":"recovery_required"})}B(),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(),B()),e.onNativeRunCompletion&&e.prepareNativeModel&&(await e.prepareNativeModel(w),B(),await(e.assertNativeTarget?.()),B()),U=Date.now(),logChatLatency(a,"claw.runtime.invoke",m,I);const E=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);E.unref?.();const S=dispatchRuntimeReplyWithRoute({runtime:n,pluginConfig:e.pluginConfig,preparedPrompt:t.dispatchInput,replyRoute:h,replySinks:{im:G},onDispatchInvoked:n=>{if(j=!0,e.onNativeRunCompletion){f=n;const t=new Promise((e,n)=>{v=e,M=n});t.catch(()=>{}),e.onNativeRunCompletion({runtimeRunId:p,token:w,hostCompletion:n,completion:t})}logChatLatency(a,"claw.runtime.dispatch_returned",m,U)}}),$=e.onNativeRunCompletion?await S:await Promise.race([S,N]).finally(()=>{});e.onNativeRunCompletion&&(await f,await b);const C=Y.detectedFailure();if(C)throw new Error(C.diagnosticMessage);if(B(),await V("success"),e.onNativeRunCompletion&&await b,B(),!i.claimTerminal(y,"completion")){if(B(),"cancelling"===i.phase(y))throw new Error("cancellation in progress");throw new Error("terminal outcome already claimed")}if(!await ee("completed"))return await failMessageStream(D,{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",...W?{recovery:W}:{}}),!1;const q=G.dispatcher.getTerminalErrorText?.();if(void 0!==q){let n=!1;const r=classifyAgentRuntimeFailure({raw:q,source:"im_runtime",runtimeKind:"openclaw"});try{await writeRuntimeFailure(D,{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&&J&&u.activeRuns.markTerminal(J,"failed"),a.warn?.(`[im] runtime dispatch ended with an error terminal requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} counts=${JSON.stringify($.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 _("",q),!1}let O=!1;try{await D.finalize({stopReason:"end_turn"})}catch(e){O=!0,a.warn?.(`[im] runtime reply stream finalize outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}u&&J&&u.activeRuns.markTerminal(J,"completed");const k={...$.counts,source:Q.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:O?"outcome_unknown":"completed",tool_count:k.tool}),e.onLifecycleEvent?.({type:"dispatch_complete",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,counts:k,...O?{terminalWriteFailed:!0}:{}});const L=G.dispatcher.getAccumulatedBody?.()??"";O||await _(L,"");const A="string"==typeof t.dispatchInput.message?t.dispatchInput.message:"";return maybeRenameImConversationTitle({client:r,conversationId:t.channelId,question:A,answer:L,logger:a}),!0}catch(n){S=n,e.onNativeRunCompletion&&(await(f?.then(()=>{},()=>{})),await b),await V("failure"),e.onNativeRunCompletion&&await b;const r=E.signal.aborted,o=r?E.signal.reason:void 0,s="cancelling"===i.phase(y),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(y,p)){if(a.warn?.(`[im] terminal claim raced requestId=${m} channel=${t.channelId}; best-effort envelope terminal if still streaming`),!D.isTerminated)try{l?await D.cancel({stopReason:"user_stop"}):await failMessageStream(D,{body:formatErrMessage(n),stopReason:"error"})}catch(e){a.warn?.(`[im] raced terminal write failed requestId=${m}: ${formatErrMessage(e)}`)}throw n}const g=l?"cancelled":"error";if(u&&J&&!e.onNativeRunCompletion&&u.activeRuns.markTerminal(J,"cancelled"===g?"cancelled":"failed"),w&&!await ee(g)){if(e.onNativeRunCompletion)throw new Error(SESSION_RECOVERY_REQUIRED_CODE);throw l?await D.cancel({stopReason:"user_stop"}).catch(()=>{}):await failMessageStream(D,{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:d,...W?{recovery:W}:{}}),n}u&&J&&e.onNativeRunCompletion&&u.activeRuns.markTerminal(J,"cancelled"===g?"cancelled":"failed");const h=classifyAgentRuntimeFailure({raw:n,source:"im_runtime",runtimeKind:"openclaw",requestAborted:l}),R=l?h:Y.detectedFailure()??h;let v=!1;try{l?await D.cancel({stopReason:"user_stop"}):await writeRuntimeFailure(D,{body:R.publicMessage,stopReason:messageStopReasonForRuntimeFailure(R),businessErrorCode:R.businessErrorCode})}catch(e){v=!0,a.warn?.(`[im] runtime stream terminal write failed requestId=${m} channel=${t.channelId}: ${formatErrMessage(e)}`)}throw a.warn?.(`[im] runtime dispatch failed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} cause=${d} dispatchInvoked=${j} 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||v||await _("",R.publicMessage),n}finally{e.onNativeRunCompletion&&(z?v?.(z):(j&&w&&l.requireRecovery(w,"terminal_not_observed"),M?.(S??new Error(SESSION_RECOVERY_REQUIRED_CODE)))),e.abortSignal?.removeEventListener("abort",K),k(),Z?.(),X?.(),H?.(),i.unregister(y),j?z&&l.release(z):l.releaseBeforeRuntime(w)}};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- 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{NodeRuntimeDeliveryPort}from"@beeos-ai/cloud-agent-sdk";import{MessageServiceConversationRunBoundary}from"./runtime/message-service-conversation-run-boundary.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,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{loadAgentKeyPair,agentBoundFetch,agentFetch}from"./agent-auth.js";import{readDiscoveryCache,writeDiscoveryCache}from"./discovery-cache.js";import{discoverBridgeFromGW}from"./bridge-discovery.js";import{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{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{CONNECTOR_MCP_PROXY_PATH,handleConnectorMcpRequest}from"./mcp-connector-proxy.js";import{CanvasStateManager}from"./canvas/state.js";import{CanvasRelayClient}from"./canvas/relay-client.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,createRenderUiHandler,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{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{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,sharedCanvasState=null,sharedAcpServer=null;const sharedSessionWriteGate=new SessionWriteGate,sharedPromptRunStore=new PromptRunStore;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,sharedModelCallObservationRouter=new ModelCallObservationRouter;let sharedSessionMutationCoordinator,sharedRuntimeAuthority;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 ensureRegisterToolCache=e=>{rawRegisterTool||(rawRegisterTool=e.registerTool.bind(e),wrappedRegisterTool=e=>(cachedCapabilityTools.push(e),rawRegisterTool(e)),e.registerTool=wrappedRegisterTool)},ED25519_PKCS8_PREFIX=Buffer.from("302e020100300506032b657004220420","hex");function agentKeyPairToIdentity(e){return{publicKeyBase64:()=>Buffer.from(e.publicKey).toString("base64"),sign:async t=>{const{createPrivateKey:r,sign:o}=await import("node:crypto"),n=r({key:32===e.privateKey.length?Buffer.concat([ED25519_PKCS8_PREFIX,Buffer.from(e.privateKey)]):Buffer.from(e.privateKey),format:"der",type:"pkcs8"});return new Uint8Array(o(null,Buffer.from(t),n))}}}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),n=r instanceof Error?r.stack:void 0;e.logger.error?.(`[beeos-claw] unhandledRejection: ${o}${n?`\n${n}`:""}`),t({component:"plugin",domain:"fatal",name:"unhandled_rejection",severity:"error",summary:o,error:{code:"unhandled_rejection",message:o,...n?{stack:n}:{}}})}),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,n=buildThirdPartyChannelSet(t);n.size>0&&e.logger.info?.(`[beeos-claw] Third-party channels detected: ${[...n].join(", ")}`);const a=o.log.enabled?createObsEventWriter({dir:o.log.dir,redaction:{gatewayToken:o.gateway.token},logger:e.logger}):()=>{};a({component:"plugin",domain:"lifecycle",name:"lifecycle.startup",severity:"info",payload:{pluginVersion:PLUGIN_VERSION,pid:process.pid,nodeVersion:process.version,cwd:process.cwd()}}),a({component:"plugin",domain:"config",name:"config.resolved",severity:"info",payload:{config:o,sources:r.sources,openclawConfigPath:r.openclawConfigPath}});for(const t of r.validation)a({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);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 agentKeys&&o.agentGatewayUrl&&(setUploadDeps({gatewayUrl:o.agentGatewayUrl,keys:agentKeys,logger:e.logger}),registerLocalFileExtractor(browserScreenshotExtractor),registerLocalFileExtractor(deliverableFileExtractor),e.logger.info?.("[beeos-claw] Upload deps + local file extractors registered")),lastOpenclawConfig=t,{cfg:o,writeObs:a,thirdPartyChannels:n,openclawConfig:t}}function registerUploadTools(e,t,r){const{cfg:o,writeObs:n}=t;cleanupUploadToolResultCache().catch(t=>{e.logger.warn?.(`[beeos_upload_file] cache cleanup failed on startup: ${String(t)}`)}),e.registerTool({name:BEEOS_UPLOAD_TOOL_NAME,description:BEEOS_UPLOAD_TOOL_DESCRIPTION,parameters:BEEOS_UPLOAD_TOOL_SCHEMA,async execute(t,r,a){e.logger.debug?.(`[beeos_upload_file] toolCallId=${t} params=${JSON.stringify(r)}`);const i=await executeUpload(r,o,agentKeys,a);return e.logger.debug?.(`[beeos_upload_file] toolCallId=${t} ok=${i.ok}`),n({component:"upload-tool",domain:"tool",name:i.ok?"upload.success":"upload.failure",severity:i.ok?"info":"warn",payload:{toolCallId:t,ok:i.ok,fileCount:i.files?.length??0,error:i.error}}),(async r=>{try{await writeUploadToolResult(t,BEEOS_UPLOAD_TOOL_NAME,r),await cleanupUploadToolResultCache()}catch(r){e.logger.warn?.(`[beeos_upload_file] persist cache failed toolCallId=${t}: ${String(r)}`)}return r})(i)}}),e.registerTool({name:BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,description:BEEOS_DESKTOP_SCREENSHOT_TOOL_DESCRIPTION,parameters:BEEOS_DESKTOP_SCREENSHOT_TOOL_SCHEMA,async execute(t,r,a){e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${t} params=${JSON.stringify(r)}`);const i=await executeDesktopScreenshot(r,o,agentKeys,a);return e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${t} ok=${i.ok}`),n({component:"desktop-screenshot-tool",domain:"tool",name:i.ok?"desktop_screenshot.success":"desktop_screenshot.failure",severity:i.ok?"info":"warn",payload:{toolCallId:t,ok:i.ok,path:i.path,fileCount:i.files?.length??0,error:i.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})(i)}}),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,a){e.logger.debug?.(`[beeos_list_files] toolCallId=${t} params=${JSON.stringify(r)}`);const i=await executeListFiles(r,o,agentKeys,a);return n({component:"file-list-tool",domain:"tool",name:i.ok?"list_files.success":"list_files.failure",severity:i.ok?"info":"warn",payload:{toolCallId:t,ok:i.ok,fileCount:i.files?.length??0,error:i.error}}),i}}),e.registerTool({name:BEEOS_FETCH_FILE_TOOL_NAME,description:BEEOS_FETCH_FILE_TOOL_DESCRIPTION,parameters:BEEOS_FETCH_FILE_TOOL_SCHEMA,async execute(t,r,a){e.logger.debug?.(`[beeos_fetch_file] toolCallId=${t} params=${JSON.stringify(r)}`);const i=await executeFetchFile(r,o,agentKeys,{signal:a,resolvePath:e.resolvePath});return n({component:"file-fetch-tool",domain:"tool",name:i.ok?"fetch_file.success":"fetch_file.failure",severity:i.ok?"info":"warn",payload:{toolCallId:t,ok:i.ok,path:i.path,size:i.size,error:i.error}}),i}})}function registerConnectorMcpProxy(e,t){e.registerHttpRoute({path:CONNECTOR_MCP_PROXY_PATH,auth:"plugin",async handler(r,o){await handleConnectorMcpRequest(r,o,{agentGatewayUrl:t.cfg.agentGatewayUrl,agentKeys:agentKeys,logger:e.logger})}})}function registerServices(e,t,r){const{cfg:o,writeObs:n,thirdPartyChannels:a}=t;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("after_tool_call",(t,r)=>{const o=r.sessionKey,n=t.toolCallId??r.toolCallId,a=t.toolName||r.toolName;if(!o||!n||!a)return void e.logger.debug?.(`[after_tool_call] ignored structured result without correlation sessionKey=${o??"missing"} toolCallId=${n??"missing"}`);observeToolCallForDelivery(t,o);sharedToolResultObservationRouter.route(o,{toolCallId:n,toolName:a,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 i=agentKeys?(e,t)=>agentFetch(e,agentKeys,t):void 0,s=agentKeys?(e,t)=>agentBoundFetch(e,agentKeys,t):void 0,l=agentKeys?Buffer.from(agentKeys.publicKey).toString("base64"):void 0,c=join(process.env.OPENCLAW_HOME||join(homedir(),".openclaw"),"beeos"),g=sharedInboundExecutionJournal??=new FileInboundExecutionJournal(join(c,"inbound-execution-journal.v1.jsonl"));sharedMcpProjection??=new OpenClawNativeMcpProjection,!sharedMcpCredentialVault&&agentKeys&&l&&(sharedMcpCredentialVault=new LocalEncryptedCredentialReferenceVault(join(c,"mcp-credential-vault.json"),l,agentKeys.privateKey));const u=cloudRuntimeTargetInstanceId(process.env);if(u&&(!agentKeys||!o.agentGatewayUrl||!i||!s))throw new Error("Cloud runtime authority requires an agent identity and gateway transport");if(sharedRuntimeAuthority&&sharedRuntimeAuthority.cloudTargetInstanceId!==u)throw new Error("Cloud runtime authority target changed during process lifetime");if(!sharedRuntimeAuthority&&agentKeys&&o.agentGatewayUrl&&i&&s&&(sharedRuntimeAuthority=new RuntimeProductionAuthority({stateDirectory:c,agentGatewayUrl:o.agentGatewayUrl,agentFetch:i,boundAgentFetch:s,keys:agentKeys,targetInstanceId:u,logger:e.logger,getMSConnectionStatus:e=>sharedMSConnectionStatus.get(e)})),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}}),sharedRuntimeAgentCapabilities??={canvas:o.canvasEnabled,terminal:!1,webSsh:!1,fileSystem:!0,image:!0,audio:!1,mcp:!0,cron:!0,streaming:!0,pushNotifications:o.messageBus.enabled},!sharedAgentProjection&&sharedRuntimeAuthority&&i&&o.agentGatewayUrl){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({agentGatewayUrl:o.agentGatewayUrl,boundAgentFetch:t.boundAgentFetch,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 d=sharedRuntimeOwner;sharedSessionMutationCoordinator??=new SessionMutationCoordinator(sharedSessionWriteGate,new OpenClawSessionWriteQuiescence(e.logger,{agentId:o.gateway.agentId||"main"}),e.logger,{onRecoveryRequired:t=>{scheduleProcessRuntimeRestart(t,e.logger)}});const m=sharedSessionMutationCoordinator;if(!sharedAcpServer){const t=sharedRuntimeAuthority&&o.agentGatewayUrl?new AgentGatewayTemplateOriginReporter({agentGatewayUrl:o.agentGatewayUrl,boundAgentFetch:sharedRuntimeAuthority.boundAgentFetch}):void 0;sharedAcpServer=new ACPServer(o,e.logger,m,n,i,l,a,sharedTerminalManager,sharedRuntimeAuthority,void 0,sharedMcpProjection,sharedMcpCredentialVault,s,{gateway:d.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:n})),runExclusive:(t,r,o)=>sharedImHotPathDeferral.runExclusive(t,r,e.logger,o)})}const p=sharedAcpServer,y=()=>sharedAgentMappings.snapshot()?.values().next().value;r.current=p,sharedMcpNativeProjectionNudge.request({registrationMode:e.registrationMode,fingerprint:fingerprintMcpServers(t.openclawConfig),logger:e.logger});const h=sharedPromptRunStore,{enabled:f,principalId:v,a2aEnabled:w}=o.messageBus;let R;!u&&o.agentGatewayUrl&&agentKeys&&(R=createBeeosClawMessageTokenProvider({agentGatewayUrl:o.agentGatewayUrl,identity:agentKeyPairToIdentity(agentKeys)}));const C=process.env.MESSAGE_RUNTIME_DELIVERY_KEY?.trim(),b=v||process.env.BEEOS_PRINCIPAL_ID||"",S=R?sharedMessageClientOwner.configure({tokenProvider:R,identityId:b,...o.messageBus.serviceUrl?{serviceUrl:o.messageBus.serviceUrl}:{},logger:e.logger,...sharedRuntimeAuthority&&C?{runtimeDelivery:{scopedDeliveryKey:C,authority:{currentLease:()=>{const e=sharedRuntimeAuthority?.authorityLease,t=sharedRuntimeAuthority?.currentConsumerBinding();return e&&t?{...e,journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}:null}}}}:{}}):void 0,_=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,E=u&&o.messageBus.serviceUrl&&sharedRuntimeAuthority?createNativeCloudChatComposition({authority:nativeCloudChatAuthorityFromRuntimeAuthority(sharedRuntimeAuthority),serviceUrl:o.messageBus.serviceUrl,logger:e.logger}):void 0,O=sharedRuntimeAuthority,A=o.messageBus.serviceUrl;if(S&&O&&A&&C){const e=S.nodeTransport;p.setCronConversationDelivery({deliver:async t=>{const r=O.authorityLease;if(!r)throw new Error("current runtime authority lease unavailable for cron delivery");const o=new MessageServiceCronDeliveryHttpAuthority({messageServiceUrl:A,fetchAuthorized:async(t,o)=>await e.fetchRuntimeChannel(t,{runtimeLeaseCredential:r.runtimeLeaseCredential},o)});return await o.deliver({...t,runtimeLeaseCredential:r.runtimeLeaseCredential})}})}else p.setCronConversationDelivery(void 0);const I=sharedRuntimeAuthority?.journal??new FileRuntimeCommandJournal(join(c,"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)}`)}),T=d.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 n=await createRuntimeServiceProductionCandidate({...o.agentGatewayUrl&&i?{authorizationAdapter:new AgentGatewayGrantJwksReadinessAdapter({agentGatewayUrl:o.agentGatewayUrl})}:{},...S&&o.agentGatewayUrl&&s&&C?{transportAdapter:new RuntimeServiceTransportReadinessAdapter({agentGatewayUrl:o.agentGatewayUrl,messageService:S.nodeTransport,messageClient:S.client,configuredServiceUrl:o.messageBus.serviceUrl,boundAgentFetch:s,scopedDeliveryKey:C})}:{},..._&&o.agentGatewayUrl&&s&&o.messageBus.serviceUrl?{cloudTransportAdapter:new CloudRuntimeServiceTransportReadinessAdapter({agentGatewayUrl:o.agentGatewayUrl,boundAgentFetch:s,configuredServiceUrl:o.messageBus.serviceUrl,runtimeDelivery:_,...E?{sessionNewConversation:E.sessionNewConversation,nativePrompt:{http:E.http,inputFiles:new NativeInputFilesHttpClient(o.agentGatewayUrl,()=>sharedRuntimeAuthority.authorityLease,(e,t)=>fetch(e,t)),runBoundary:new MessageServiceConversationRunBoundary({transport:{start:e=>_.startConversationRun(e),finish:e=>_.finishConversationRun(e)}}),host:{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:h,assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,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:I,poisonJournal:new FileRuntimePoisonDeliveryJournal(join(c,"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"),n="string"==typeof r.code&&/^[A-Za-z0-9_.:-]{1,64}$/.test(r.code)?r.code:"unavailable",a="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=${n} status=${a}`)},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"===n.status?n.serviceMethods:[]),sharedRuntimeAuthority?.setRuntimeResourceBindingContractRevision("ready"===n.status?n.resourceBindingContractRevision:void 0),p.setRuntimeRpcConsumerFactory("ready"===n.status?n.factory:void 0),"unavailable"===n.status?e.logger.warn?.("[runtime-service] capability fenced: "+n.blockers.map(e=>e.id).join(",")):n.capabilityBlockers.length&&e.logger.warn?.("[runtime-service] method capability fenced: "+n.capabilityBlockers.map(e=>e.method).join(",")),!o.bridge.url&&o.agentGatewayUrl&&i){const t=Date.now(),r=await discoverBridgeFromGW(o.agentGatewayUrl,i);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 d.acquire(T);try{await p.start(o.bridge.url||void 0)}catch(e){throw await d.release(T),e}e.logger.info?.(`[beeos-claw] ACP Server started (total service start: ${Date.now()-t}ms)`)},async stop(){try{await d.release(T)}finally{await p.stop()}await I.checkpoint(),e.logger.info?.("[runtime-service] command journal checkpoint completed"),e.logger.info?.("[beeos-claw] ACP Server stopped")}});if(f&&void 0!==R&&R){const t=sharedMessageClientOwner.createRegistrationToken(),r=async(e,t)=>{const r=await R(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}},a=(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)}),i=sharedRuntimeAuthority?new RuntimeAuthorityMessageBusLifecycle({authority:sharedRuntimeAuthority,logger:e.logger,bus:{connect:async i=>{await sharedMessageClientOwner.acquire(t,async t=>{const s=await r(i.instanceId,i.runtimeEpoch),l=t.client,c={leaseId:i.leaseId,runtimeEpoch:i.runtimeEpoch};sharedMSConnectionStatus.bind(c);const u=new Map,d=new MessageProjectionInboundConsumer({client:l,bindings:()=>{const t=sharedRuntimeAuthority?.authorityLease;if(!t||t.instanceId!==s.principalId||t.runtimeEpoch!==s.runtimeEpoch)return[];const r=sharedAgentMappings.snapshot();return r?[...r.entries()].flatMap(([r,i])=>{if(!i.id||i.instanceId!==s.principalId)return[];let c=u.get(i.id);return c&&c.localAgentId===r||(c={localAgentId:r,inbound:createImInboundHandler({runtime:e.runtime,pluginConfig:e.pluginConfig,client:l,localServer:a(s,r,i.id),promptRunStore:h,waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{}),assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:m,logger:e.logger,writeObs:n,principalIdOverride:s.principalId,activeRunAuthority:p.getActiveRunAuthority(),...o.agentGatewayUrl&&agentKeys?{completeA2ATask:(t,r,n)=>completeA2ATask({agentGatewayUrl:o.agentGatewayUrl,agentKeys:agentKeys,logger:e.logger},t,r,n)}:{}})},u.set(i.id,c)),[{principalId:s.principalId,targetAgentId:i.id,runtimeEpoch:t.runtimeEpoch,inbound:c.inbound}]}):[]},executionJournal:g,logger:e.logger}),y=sharedAgentMappings.subscribe(()=>{sharedActiveMessageConsumer===d&&d.refresh()}),f=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===s.principalId&&e.runtimeEpoch===s.runtimeEpoch&&e.leaseId===i.leaseId&&e.handlerIdentity===i.handlerIdentity},reconnect:async()=>{if("failed"===l.getSnapshot().connection){await l.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=l.getSnapshot().connection;sharedMSConnectionStatus.setIfCurrent(c,w);const R=l.subscribe(()=>{const t=l.getSnapshot();t.connection!==w&&(w=t.connection,sharedMSConnectionStatus.setIfCurrent(c,t.connection),"connected"===t.connection?(v.notifyConnected(),e.logger.info?.(`[beeos-claw] connection transport=message_service_realtime state=connected localAgentId=${p.getLocalAgentId()} principalId=${s.principalId}`)):"failed"===t.connection?(e.logger.warn?.(`[beeos-claw] connection transport=message_service_realtime state=failed principalId=${s.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=${s.principalId}; SDK owns reconnect/recovery`))});sharedActiveMessageConsumer=d,d.start();try{await l.connect()}catch(e){throw sharedActiveMessageConsumer===d&&(sharedActiveMessageConsumer=void 0),sharedMSConnectionStatus.resetIfCurrent(c),v.dispose(),await d.stop(),y(),f(),R(),await l.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(c),v.dispose(),await d.stop(),f(),R(),await l.disconnect(),e.logger.info?.("[beeos-claw] MessageClient disconnected")}})},disconnect:async()=>{await sharedMessageClientOwner.release(t)}}}):void 0;e.registerService({id:"beeos-message-bus",async start(){i?i.start():e.logger.warn?.("[beeos-claw] Message bus requires runtime authority; waiting is unavailable without Agent Gateway runtime identity")},async stop(){await(i?.stop())}})}else f?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=${f})`);if(f&&E&&sharedRuntimeAuthority){const t=E,r=sharedRuntimeAuthority;let a;const i=new Map,s=(r,a)=>{const s=sharedAgentMappings.snapshot();if(s)for(const[l,c]of s.entries()){if(c.id!==a)continue;if(c.instanceId!==r.instanceId)continue;const s=`${l}\0${c.id}`;let g=i.get(s);return g||(g={localAgentId:l,inbound:createImInboundHandler({runtime:e.runtime,pluginConfig:e.pluginConfig,client:t.adapter,localServer:{getLocalAgentId:()=>l,resolveLocalAgentId:e=>e===c.id?l:void 0,getDefaultPlatformAgent:()=>({instanceId:r.instanceId}),ensureImInboundSession:(e,t,r,o)=>{p.ensureImInboundSession(e,t,r,o)},chatAbort:(e,t)=>p.chatAbort(e,t)},promptRunStore:h,waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{}),assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:m,logger:e.logger,writeObs:n,principalIdOverride:r.instanceId,activeRunAuthority:p.getActiveRunAuthority(),...o.agentGatewayUrl&&agentKeys?{completeA2ATask:(t,r,n)=>completeA2ATask({agentGatewayUrl:o.agentGatewayUrl,agentKeys:agentKeys,logger:e.logger},t,r,n)}:{}})},i.set(s,g)),g}},l=new RuntimeAuthorityMessageBusLifecycle({authority:r,logger:e.logger,bus:{connect:async r=>{a?.(),i.clear(),a=t.adapter.listen({eventTypes:["message.created"]},t=>{const o=(t.content??{}).metadata??{},n="string"==typeof o.target_agent_id?o.target_agent_id:"",a=n?s(r,n):void 0;if(!a)return void e.logger.warn?.(`[beeos-claw] native cloud chat dropped unresolvable target_agent_id=${n||"missing"} message_id=${t.id}`);("chat_cancel"===t.type?a.inbound.onChatCancel(t):a.inbound.onChatMessage(t)).catch(r=>{e.logger.error?.(`[beeos-claw] native cloud chat dispatch failed message_id=${t.id}: ${r instanceof Error?r.message:String(r)}`)})});try{await t.adapter.connect()}catch(e){throw a?.(),a=void 0,e}},disconnect:async()=>{a?.(),a=void 0,i.clear(),await t.adapter.disconnect()}}});e.registerService({id:"beeos-native-cloud-chat",async start(){l.start()},async stop(){await l.stop()}}),e.logger.info?.("[beeos-claw] native Cloud personal-chat composition registered")}else f&&u&&!E&&e.logger.warn?.("[beeos-claw] Cloud message bus enabled but native composition unavailable (messageBus.serviceUrl or runtime authority missing) — disabled");if(!1!==w&&o.agentGatewayUrl){const t=e=>p.getGatewaySessionKeyForToolCall(e),r=e=>p.getMentionsForToolCall(e),n=(e,t)=>{p.broadcastNotification(e,t)},a=new TaskHandleRegistry;registerA2ATools(e,{agentGatewayUrl:o.agentGatewayUrl,agentKeys:agentKeys,logger:e.logger},a,t,r,n,()=>y()?.instanceId),e.logger.info?.("[beeos-claw] A2A tools registered (beeos_discover_agents, beeos_call_agent) via REST")}if(o.canvasEnabled){sharedCanvasState||(sharedCanvasState=new CanvasStateManager);const t=sharedCanvasState;if(o.agentGatewayUrl&&agentKeys){let r;t.setLogger(e.logger);{const e=o.agentGatewayUrl,t=agentKeys;r=async()=>{const r=await agentFetch(`${e}/api/v1/canvas/token`,t,{method:"POST",headers:{"content-type":"application/json"},body:"{}"});if(!r.ok){const e=await r.text().catch(()=>"");throw new Error(`Canvas token returned ${r.status}: ${e}`)}return r.json()}}const n=n=>{const a=new CanvasRelayClient({canvasRelayUrl:o.canvasRelayUrl,agentKeys:agentKeys,agentId:n.id,displayName:n.displayName,avatarUrl:n.avatarUrl,tokenProvider:r,onConnected:()=>p.flushPendingCanvasLinks(),onReconnect:()=>p.onRelayReconnected(),logger:e.logger});t.setRelayClient(a),t.setAgentId(n.id),p.wireRelayActionHandler(),a.connect(),e.logger.info?.(`[beeos-claw] Canvas Relay multiplexed client connected (agentId=${n.id}, name=${n.name??"none"})`)};e.registerService(createCanvasRelayService({getAgent:y,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=>n(e),getActiveSessionId:e=>p.getSessionIdForToolCall(e),getPlatformAgentId:e=>p.getPlatformAgentIdForToolCall(e),getGatewaySessionKey:e=>p.getGatewaySessionKeyForToolCall(e),waitForAgentSync:()=>sharedAgentMappings.waitForSynchronization()},i=new FormSchemaRegistry,s=buildCronSchemas(a);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(createRenderUiHandler(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 g=p.getFormBuilder();g&&e.registerTool({name:RENDER_FORM_TOOL_NAME,description:buildRenderFormDescription(i),parameters:RENDER_FORM_TOOL_SCHEMA,execute:c(createRenderFormHandler({registry:i,builder:g,logger:e.logger}))});const u=p.getResourceRenderer();if(u){generateActionTools(l,e,async(e,t)=>p.gatewayRequest(e,t),u,e.logger)}const d=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]),h=256,f=new Map;if("function"==typeof e.on){try{e.on("before_prompt_build",(e,t)=>{if(t?.sessionKey){if(f.size>=h&&!f.has(t.sessionKey)){const e=f.keys().next().value;void 0!==e&&f.delete(e)}f.set(t.sessionKey,t.channelId),rememberDeliveryWorkspace(t.sessionKey,t.workspaceDir)}const r=isThirdPartyChannel(a,{sessionKey:t?.sessionKey,channelId:t?.channelId});return t?.sessionKey||r?{appendSystemContext:buildAppendSystemContext({thirdParty:r,canvasSystemPrompt:`${CANVAS_PRESENTATION_GATE}\n\n${CANVAS_SYSTEM_PROMPT}`,toolRoutingHint:d})}:{appendSystemContext:d}}),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?f.get(t.sessionKey):void 0,o=isThirdPartyChannel(a,{sessionKey:t?.sessionKey,channelId:r}),n=canvasToolBlockReason({thirdParty:o,hasSession:Boolean(t?.sessionKey)});return n?{block:!0,blockReason:n}: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:n});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}`)}}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;const t=planPluginRegistration(e.registrationMode,_fullRuntimeRegistered);if("skip"!==t){_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 r=(t,r)=>{registerUploadTools(e,t,r),registerConnectorMcpProxy(e,t),registerArouterLatencyRouting(e),registerArouterMediaProviders(e)};if("capabilities"===t&&sharedPluginContext){if(cachedCapabilityTools.length>0){const t=resolveCapabilityToolReplay({currentRegisterTool:e.registerTool,wrappedRegisterTool:wrappedRegisterTool,originalRegisterTool:rawRegisterTool}),r=replayCachedPluginTools(r=>t.call(e,r),cachedCapabilityTools);return registerArouterLatencyRouting(e),registerArouterMediaProviders(e),void e.logger.info?.(`[beeos-claw] capability re-register mode=${e.registrationMode} tools_only count=${r}`)}const t={current:sharedAcpServer??null};return r(sharedPluginContext,t),registerServices(e,sharedPluginContext,t),void e.logger.info?.(`[beeos-claw] capability re-register mode=${e.registrationMode} capabilities_only`)}const o=initializePlugin(e);if(!o)return;const n={current:null};installUnhandledRejectionObserver(e,o.writeObs,n),ensureRegisterToolCache(e),cachedCapabilityTools.length=0,r(o,n),agentKeys&&o.cfg.agentGatewayUrl&&(e.on?e.on("before_agent_finalize",fileDeliveryFinalizeDecision):e.logger.warn?.("[file-delivery] OpenClaw plugin hooks unavailable; finalization check disabled")),registerServices(e,o,n),sharedPluginContext=o,marksFullRuntimeRegistered(e.registrationMode,t)&&(_fullRuntimeRegistered=!0),_pluginRegisteredAt=Date.now(),e.logger.info?.("[beeos-claw] Plugin registered successfully")}finally{_initializing=!1}}else e.logger.info?.(`[beeos-claw] skip re-register mode=${e.registrationMode??"full"} already_registered`)}};export default plugin;
1
+ import{prepareNativeOutputTool,consumeNativeOutputTool}from"./runtime/native-output-file-attempt.js";import{uploadNativeOutputFile}from"./upload/upload-file.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{NodeRuntimeDeliveryPort}from"@beeos-ai/cloud-agent-sdk";import{MessageServiceConversationRunBoundary}from"./runtime/message-service-conversation-run-boundary.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,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{loadAgentKeyPair,agentBoundFetch,agentFetch}from"./agent-auth.js";import{readDiscoveryCache,writeDiscoveryCache}from"./discovery-cache.js";import{discoverBridgeFromGW}from"./bridge-discovery.js";import{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{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{CONNECTOR_MCP_PROXY_PATH,handleConnectorMcpRequest}from"./mcp-connector-proxy.js";import{CanvasStateManager}from"./canvas/state.js";import{CanvasRelayClient}from"./canvas/relay-client.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,createRenderUiHandler,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{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{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,sharedCanvasState=null,sharedAcpServer=null;const sharedSessionWriteGate=new SessionWriteGate,sharedPromptRunStore=new PromptRunStore;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,sharedModelCallObservationRouter=new ModelCallObservationRouter;let sharedSessionMutationCoordinator,sharedRuntimeAuthority;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 ensureRegisterToolCache=e=>{rawRegisterTool||(rawRegisterTool=e.registerTool.bind(e),wrappedRegisterTool=e=>(cachedCapabilityTools.push(e),rawRegisterTool(e)),e.registerTool=wrappedRegisterTool)},ED25519_PKCS8_PREFIX=Buffer.from("302e020100300506032b657004220420","hex");function agentKeyPairToIdentity(e){return{publicKeyBase64:()=>Buffer.from(e.publicKey).toString("base64"),sign:async t=>{const{createPrivateKey:r,sign:o}=await import("node:crypto"),n=r({key:32===e.privateKey.length?Buffer.concat([ED25519_PKCS8_PREFIX,Buffer.from(e.privateKey)]):Buffer.from(e.privateKey),format:"der",type:"pkcs8"});return new Uint8Array(o(null,Buffer.from(t),n))}}}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),n=r instanceof Error?r.stack:void 0;e.logger.error?.(`[beeos-claw] unhandledRejection: ${o}${n?`\n${n}`:""}`),t({component:"plugin",domain:"fatal",name:"unhandled_rejection",severity:"error",summary:o,error:{code:"unhandled_rejection",message:o,...n?{stack:n}:{}}})}),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,n=buildThirdPartyChannelSet(t);n.size>0&&e.logger.info?.(`[beeos-claw] Third-party channels detected: ${[...n].join(", ")}`);const a=o.log.enabled?createObsEventWriter({dir:o.log.dir,redaction:{gatewayToken:o.gateway.token},logger:e.logger}):()=>{};a({component:"plugin",domain:"lifecycle",name:"lifecycle.startup",severity:"info",payload:{pluginVersion:PLUGIN_VERSION,pid:process.pid,nodeVersion:process.version,cwd:process.cwd()}}),a({component:"plugin",domain:"config",name:"config.resolved",severity:"info",payload:{config:o,sources:r.sources,openclawConfigPath:r.openclawConfigPath}});for(const t of r.validation)a({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);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 agentKeys&&o.agentGatewayUrl&&(setUploadDeps({gatewayUrl:o.agentGatewayUrl,keys:agentKeys,logger:e.logger}),registerLocalFileExtractor(browserScreenshotExtractor),registerLocalFileExtractor(deliverableFileExtractor),e.logger.info?.("[beeos-claw] Upload deps + local file extractors registered")),lastOpenclawConfig=t,{cfg:o,writeObs:a,thirdPartyChannels:n,openclawConfig:t}}function registerUploadTools(e,t,r){const{cfg:o,writeObs:n}=t,a=Boolean(cloudRuntimeTargetInstanceId(process.env));if(a){if(!e.on)throw new Error("native output Files Host hook unavailable");e.on("before_tool_call",(e,t)=>{if(e.toolName===BEEOS_UPLOAD_TOOL_NAME){if(e.runId&&t.runId&&e.runId!==t.runId||e.toolCallId&&t.toolCallId&&e.toolCallId!==t.toolCallId)return{block:!0,blockReason:"native output file Host correlation conflict"};try{prepareNativeOutputTool(e.runId??t.runId,e.toolCallId??t.toolCallId)}catch{return{block:!0,blockReason:"native output file trusted capability unavailable"}}}})}cleanupUploadToolResultCache().catch(t=>{e.logger.warn?.(`[beeos_upload_file] cache cleanup failed on startup: ${String(t)}`)}),e.registerTool({name:BEEOS_UPLOAD_TOOL_NAME,description:BEEOS_UPLOAD_TOOL_DESCRIPTION,parameters:BEEOS_UPLOAD_TOOL_SCHEMA,async execute(t,r,i){const s=a?consumeNativeOutputTool(t):void 0,l=await executeUpload(r,o,agentKeys,i,s?(e,t)=>uploadNativeOutputFile(e,o.agentGatewayUrl,s,t,i):void 0);return e.logger.debug?.(`[beeos_upload_file] toolCallId=${t} ok=${l.ok}`),n({component:"upload-tool",domain:"tool",name:l.ok?"upload.success":"upload.failure",severity:l.ok?"info":"warn",payload:{toolCallId:t,ok:l.ok,fileCount:l.files?.length??0,error:l.error}}),(async r=>{try{await writeUploadToolResult(t,BEEOS_UPLOAD_TOOL_NAME,r),await cleanupUploadToolResultCache()}catch(r){e.logger.warn?.(`[beeos_upload_file] persist cache failed toolCallId=${t}: ${String(r)}`)}return r})(l)}}),e.registerTool({name:BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,description:BEEOS_DESKTOP_SCREENSHOT_TOOL_DESCRIPTION,parameters:BEEOS_DESKTOP_SCREENSHOT_TOOL_SCHEMA,async execute(t,r,a){e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${t} params=${JSON.stringify(r)}`);const i=await executeDesktopScreenshot(r,o,agentKeys,a);return e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${t} ok=${i.ok}`),n({component:"desktop-screenshot-tool",domain:"tool",name:i.ok?"desktop_screenshot.success":"desktop_screenshot.failure",severity:i.ok?"info":"warn",payload:{toolCallId:t,ok:i.ok,path:i.path,fileCount:i.files?.length??0,error:i.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})(i)}}),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,a){e.logger.debug?.(`[beeos_list_files] toolCallId=${t} params=${JSON.stringify(r)}`);const i=await executeListFiles(r,o,agentKeys,a);return n({component:"file-list-tool",domain:"tool",name:i.ok?"list_files.success":"list_files.failure",severity:i.ok?"info":"warn",payload:{toolCallId:t,ok:i.ok,fileCount:i.files?.length??0,error:i.error}}),i}}),e.registerTool({name:BEEOS_FETCH_FILE_TOOL_NAME,description:BEEOS_FETCH_FILE_TOOL_DESCRIPTION,parameters:BEEOS_FETCH_FILE_TOOL_SCHEMA,async execute(t,r,a){e.logger.debug?.(`[beeos_fetch_file] toolCallId=${t} params=${JSON.stringify(r)}`);const i=await executeFetchFile(r,o,agentKeys,{signal:a,resolvePath:e.resolvePath});return n({component:"file-fetch-tool",domain:"tool",name:i.ok?"fetch_file.success":"fetch_file.failure",severity:i.ok?"info":"warn",payload:{toolCallId:t,ok:i.ok,path:i.path,size:i.size,error:i.error}}),i}})}function registerConnectorMcpProxy(e,t){e.registerHttpRoute({path:CONNECTOR_MCP_PROXY_PATH,auth:"plugin",async handler(r,o){await handleConnectorMcpRequest(r,o,{agentGatewayUrl:t.cfg.agentGatewayUrl,agentKeys:agentKeys,logger:e.logger})}})}function registerServices(e,t,r){const{cfg:o,writeObs:n,thirdPartyChannels:a}=t;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("after_tool_call",(t,r)=>{const o=r.sessionKey,n=t.toolCallId??r.toolCallId,a=t.toolName||r.toolName;if(!o||!n||!a)return void e.logger.debug?.(`[after_tool_call] ignored structured result without correlation sessionKey=${o??"missing"} toolCallId=${n??"missing"}`);observeToolCallForDelivery(t,o);sharedToolResultObservationRouter.route(o,{toolCallId:n,toolName:a,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 i=agentKeys?(e,t)=>agentFetch(e,agentKeys,t):void 0,s=agentKeys?(e,t)=>agentBoundFetch(e,agentKeys,t):void 0,l=agentKeys?Buffer.from(agentKeys.publicKey).toString("base64"):void 0,c=join(process.env.OPENCLAW_HOME||join(homedir(),".openclaw"),"beeos"),u=sharedInboundExecutionJournal??=new FileInboundExecutionJournal(join(c,"inbound-execution-journal.v1.jsonl"));sharedMcpProjection??=new OpenClawNativeMcpProjection,!sharedMcpCredentialVault&&agentKeys&&l&&(sharedMcpCredentialVault=new LocalEncryptedCredentialReferenceVault(join(c,"mcp-credential-vault.json"),l,agentKeys.privateKey));const g=cloudRuntimeTargetInstanceId(process.env);if(g&&(!agentKeys||!o.agentGatewayUrl||!i||!s))throw new Error("Cloud runtime authority requires an agent identity and gateway transport");if(sharedRuntimeAuthority&&sharedRuntimeAuthority.cloudTargetInstanceId!==g)throw new Error("Cloud runtime authority target changed during process lifetime");if(!sharedRuntimeAuthority&&agentKeys&&o.agentGatewayUrl&&i&&s&&(sharedRuntimeAuthority=new RuntimeProductionAuthority({stateDirectory:c,agentGatewayUrl:o.agentGatewayUrl,agentFetch:i,boundAgentFetch:s,keys:agentKeys,targetInstanceId:g,logger:e.logger,getMSConnectionStatus:e=>sharedMSConnectionStatus.get(e)})),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}}),sharedRuntimeAgentCapabilities??={canvas:o.canvasEnabled,terminal:!1,webSsh:!1,fileSystem:!0,image:!0,audio:!1,mcp:!0,cron:!0,streaming:!0,pushNotifications:o.messageBus.enabled},!sharedAgentProjection&&sharedRuntimeAuthority&&i&&o.agentGatewayUrl){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({agentGatewayUrl:o.agentGatewayUrl,boundAgentFetch:t.boundAgentFetch,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 d=sharedRuntimeOwner;sharedSessionMutationCoordinator??=new SessionMutationCoordinator(sharedSessionWriteGate,new OpenClawSessionWriteQuiescence(e.logger,{agentId:o.gateway.agentId||"main"}),e.logger,{onRecoveryRequired:t=>{scheduleProcessRuntimeRestart(t,e.logger)}});const m=sharedSessionMutationCoordinator;if(!sharedAcpServer){const t=sharedRuntimeAuthority&&o.agentGatewayUrl?new AgentGatewayTemplateOriginReporter({agentGatewayUrl:o.agentGatewayUrl,boundAgentFetch:sharedRuntimeAuthority.boundAgentFetch}):void 0;sharedAcpServer=new ACPServer(o,e.logger,m,n,i,l,a,sharedTerminalManager,sharedRuntimeAuthority,void 0,sharedMcpProjection,sharedMcpCredentialVault,s,{gateway:d.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:n})),runExclusive:(t,r,o)=>sharedImHotPathDeferral.runExclusive(t,r,e.logger,o)})}const p=sharedAcpServer,y=()=>sharedAgentMappings.snapshot()?.values().next().value;r.current=p,sharedMcpNativeProjectionNudge.request({registrationMode:e.registrationMode,fingerprint:fingerprintMcpServers(t.openclawConfig),logger:e.logger});const h=sharedPromptRunStore,{enabled:f,principalId:v,a2aEnabled:w}=o.messageBus;let R;!g&&o.agentGatewayUrl&&agentKeys&&(R=createBeeosClawMessageTokenProvider({agentGatewayUrl:o.agentGatewayUrl,identity:agentKeyPairToIdentity(agentKeys)}));const C=process.env.MESSAGE_RUNTIME_DELIVERY_KEY?.trim(),b=v||process.env.BEEOS_PRINCIPAL_ID||"",_=R?sharedMessageClientOwner.configure({tokenProvider:R,identityId:b,...o.messageBus.serviceUrl?{serviceUrl:o.messageBus.serviceUrl}:{},logger:e.logger,...sharedRuntimeAuthority&&C?{runtimeDelivery:{scopedDeliveryKey:C,authority:{currentLease:()=>{const e=sharedRuntimeAuthority?.authorityLease,t=sharedRuntimeAuthority?.currentConsumerBinding();return e&&t?{...e,journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}:null}}}}:{}}):void 0,S=g&&o.messageBus.serviceUrl&&sharedRuntimeAuthority?new NodeRuntimeDeliveryPort({serviceOrigin:async()=>o.messageBus.serviceUrl},{currentLease:()=>{const e=sharedRuntimeAuthority?.authorityLease,t=sharedRuntimeAuthority?.currentConsumerBinding();return e&&t&&e.instanceId===g?{...e,journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}:null},subscribeAuthority:e=>sharedRuntimeAuthority.subscribeAuthority(e)}):void 0,O=g&&o.messageBus.serviceUrl&&sharedRuntimeAuthority?createNativeCloudChatComposition({authority:nativeCloudChatAuthorityFromRuntimeAuthority(sharedRuntimeAuthority),serviceUrl:o.messageBus.serviceUrl,logger:e.logger}):void 0,E=sharedRuntimeAuthority,A=o.messageBus.serviceUrl;if(_&&E&&A&&C){const e=_.nodeTransport;p.setCronConversationDelivery({deliver:async t=>{const r=E.authorityLease;if(!r)throw new Error("current runtime authority lease unavailable for cron delivery");const o=new MessageServiceCronDeliveryHttpAuthority({messageServiceUrl:A,fetchAuthorized:async(t,o)=>await e.fetchRuntimeChannel(t,{runtimeLeaseCredential:r.runtimeLeaseCredential},o)});return await o.deliver({...t,runtimeLeaseCredential:r.runtimeLeaseCredential})}})}else p.setCronConversationDelivery(void 0);const I=sharedRuntimeAuthority?.journal??new FileRuntimeCommandJournal(join(c,"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)}`)}),T=d.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 n=await createRuntimeServiceProductionCandidate({...o.agentGatewayUrl&&i?{authorizationAdapter:new AgentGatewayGrantJwksReadinessAdapter({agentGatewayUrl:o.agentGatewayUrl})}:{},..._&&o.agentGatewayUrl&&s&&C?{transportAdapter:new RuntimeServiceTransportReadinessAdapter({agentGatewayUrl:o.agentGatewayUrl,messageService:_.nodeTransport,messageClient:_.client,configuredServiceUrl:o.messageBus.serviceUrl,boundAgentFetch:s,scopedDeliveryKey:C})}:{},...S&&o.agentGatewayUrl&&s&&o.messageBus.serviceUrl?{cloudTransportAdapter:new CloudRuntimeServiceTransportReadinessAdapter({agentGatewayUrl:o.agentGatewayUrl,boundAgentFetch:s,configuredServiceUrl:o.messageBus.serviceUrl,runtimeDelivery:S,...O?{sessionNewConversation:O.sessionNewConversation,nativePrompt:{http:O.http,inputFiles:new NativeInputFilesHttpClient(o.agentGatewayUrl,()=>sharedRuntimeAuthority.authorityLease,(e,t)=>fetch(e,t)),runBoundary:new MessageServiceConversationRunBoundary({transport:{start:e=>S.startConversationRun(e),finish:e=>S.finishConversationRun(e)}}),host:{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:h,assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,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:I,poisonJournal:new FileRuntimePoisonDeliveryJournal(join(c,"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"),n="string"==typeof r.code&&/^[A-Za-z0-9_.:-]{1,64}$/.test(r.code)?r.code:"unavailable",a="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=${n} status=${a}`)},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"===n.status?n.serviceMethods:[]),sharedRuntimeAuthority?.setRuntimeResourceBindingContractRevision("ready"===n.status?n.resourceBindingContractRevision:void 0),p.setRuntimeRpcConsumerFactory("ready"===n.status?n.factory:void 0),"unavailable"===n.status?e.logger.warn?.("[runtime-service] capability fenced: "+n.blockers.map(e=>e.id).join(",")):n.capabilityBlockers.length&&e.logger.warn?.("[runtime-service] method capability fenced: "+n.capabilityBlockers.map(e=>e.method).join(",")),!o.bridge.url&&o.agentGatewayUrl&&i){const t=Date.now(),r=await discoverBridgeFromGW(o.agentGatewayUrl,i);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 d.acquire(T);try{await p.start(o.bridge.url||void 0)}catch(e){throw await d.release(T),e}e.logger.info?.(`[beeos-claw] ACP Server started (total service start: ${Date.now()-t}ms)`)},async stop(){try{await d.release(T)}finally{await p.stop()}await I.checkpoint(),e.logger.info?.("[runtime-service] command journal checkpoint completed"),e.logger.info?.("[beeos-claw] ACP Server stopped")}});if(f&&void 0!==R&&R){const t=sharedMessageClientOwner.createRegistrationToken(),r=async(e,t)=>{const r=await R(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}},a=(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)}),i=sharedRuntimeAuthority?new RuntimeAuthorityMessageBusLifecycle({authority:sharedRuntimeAuthority,logger:e.logger,bus:{connect:async i=>{await sharedMessageClientOwner.acquire(t,async t=>{const s=await r(i.instanceId,i.runtimeEpoch),l=t.client,c={leaseId:i.leaseId,runtimeEpoch:i.runtimeEpoch};sharedMSConnectionStatus.bind(c);const g=new Map,d=new MessageProjectionInboundConsumer({client:l,bindings:()=>{const t=sharedRuntimeAuthority?.authorityLease;if(!t||t.instanceId!==s.principalId||t.runtimeEpoch!==s.runtimeEpoch)return[];const r=sharedAgentMappings.snapshot();return r?[...r.entries()].flatMap(([r,i])=>{if(!i.id||i.instanceId!==s.principalId)return[];let c=g.get(i.id);return c&&c.localAgentId===r||(c={localAgentId:r,inbound:createImInboundHandler({runtime:e.runtime,pluginConfig:e.pluginConfig,client:l,localServer:a(s,r,i.id),promptRunStore:h,waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{}),assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:m,logger:e.logger,writeObs:n,principalIdOverride:s.principalId,activeRunAuthority:p.getActiveRunAuthority(),...o.agentGatewayUrl&&agentKeys?{completeA2ATask:(t,r,n)=>completeA2ATask({agentGatewayUrl:o.agentGatewayUrl,agentKeys:agentKeys,logger:e.logger},t,r,n)}:{}})},g.set(i.id,c)),[{principalId:s.principalId,targetAgentId:i.id,runtimeEpoch:t.runtimeEpoch,inbound:c.inbound}]}):[]},executionJournal:u,logger:e.logger}),y=sharedAgentMappings.subscribe(()=>{sharedActiveMessageConsumer===d&&d.refresh()}),f=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===s.principalId&&e.runtimeEpoch===s.runtimeEpoch&&e.leaseId===i.leaseId&&e.handlerIdentity===i.handlerIdentity},reconnect:async()=>{if("failed"===l.getSnapshot().connection){await l.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=l.getSnapshot().connection;sharedMSConnectionStatus.setIfCurrent(c,w);const R=l.subscribe(()=>{const t=l.getSnapshot();t.connection!==w&&(w=t.connection,sharedMSConnectionStatus.setIfCurrent(c,t.connection),"connected"===t.connection?(v.notifyConnected(),e.logger.info?.(`[beeos-claw] connection transport=message_service_realtime state=connected localAgentId=${p.getLocalAgentId()} principalId=${s.principalId}`)):"failed"===t.connection?(e.logger.warn?.(`[beeos-claw] connection transport=message_service_realtime state=failed principalId=${s.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=${s.principalId}; SDK owns reconnect/recovery`))});sharedActiveMessageConsumer=d,d.start();try{await l.connect()}catch(e){throw sharedActiveMessageConsumer===d&&(sharedActiveMessageConsumer=void 0),sharedMSConnectionStatus.resetIfCurrent(c),v.dispose(),await d.stop(),y(),f(),R(),await l.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(c),v.dispose(),await d.stop(),f(),R(),await l.disconnect(),e.logger.info?.("[beeos-claw] MessageClient disconnected")}})},disconnect:async()=>{await sharedMessageClientOwner.release(t)}}}):void 0;e.registerService({id:"beeos-message-bus",async start(){i?i.start():e.logger.warn?.("[beeos-claw] Message bus requires runtime authority; waiting is unavailable without Agent Gateway runtime identity")},async stop(){await(i?.stop())}})}else f?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=${f})`);if(f&&O&&sharedRuntimeAuthority){const t=O,r=sharedRuntimeAuthority;let a;const i=new Map,s=(r,a)=>{const s=sharedAgentMappings.snapshot();if(s)for(const[l,c]of s.entries()){if(c.id!==a)continue;if(c.instanceId!==r.instanceId)continue;const s=`${l}\0${c.id}`;let u=i.get(s);return u||(u={localAgentId:l,inbound:createImInboundHandler({runtime:e.runtime,pluginConfig:e.pluginConfig,client:t.adapter,localServer:{getLocalAgentId:()=>l,resolveLocalAgentId:e=>e===c.id?l:void 0,getDefaultPlatformAgent:()=>({instanceId:r.instanceId}),ensureImInboundSession:(e,t,r,o)=>{p.ensureImInboundSession(e,t,r,o)},chatAbort:(e,t)=>p.chatAbort(e,t)},promptRunStore:h,waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{}),assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:m,logger:e.logger,writeObs:n,principalIdOverride:r.instanceId,activeRunAuthority:p.getActiveRunAuthority(),...o.agentGatewayUrl&&agentKeys?{completeA2ATask:(t,r,n)=>completeA2ATask({agentGatewayUrl:o.agentGatewayUrl,agentKeys:agentKeys,logger:e.logger},t,r,n)}:{}})},i.set(s,u)),u}},l=new RuntimeAuthorityMessageBusLifecycle({authority:r,logger:e.logger,bus:{connect:async r=>{a?.(),i.clear(),a=t.adapter.listen({eventTypes:["message.created"]},t=>{const o=(t.content??{}).metadata??{},n="string"==typeof o.target_agent_id?o.target_agent_id:"",a=n?s(r,n):void 0;if(!a)return void e.logger.warn?.(`[beeos-claw] native cloud chat dropped unresolvable target_agent_id=${n||"missing"} message_id=${t.id}`);("chat_cancel"===t.type?a.inbound.onChatCancel(t):a.inbound.onChatMessage(t)).catch(r=>{e.logger.error?.(`[beeos-claw] native cloud chat dispatch failed message_id=${t.id}: ${r instanceof Error?r.message:String(r)}`)})});try{await t.adapter.connect()}catch(e){throw a?.(),a=void 0,e}},disconnect:async()=>{a?.(),a=void 0,i.clear(),await t.adapter.disconnect()}}});e.registerService({id:"beeos-native-cloud-chat",async start(){l.start()},async stop(){await l.stop()}}),e.logger.info?.("[beeos-claw] native Cloud personal-chat composition registered")}else f&&g&&!O&&e.logger.warn?.("[beeos-claw] Cloud message bus enabled but native composition unavailable (messageBus.serviceUrl or runtime authority missing) — disabled");if(!1!==w&&o.agentGatewayUrl){const t=e=>p.getGatewaySessionKeyForToolCall(e),r=e=>p.getMentionsForToolCall(e),n=(e,t)=>{p.broadcastNotification(e,t)},a=new TaskHandleRegistry;registerA2ATools(e,{agentGatewayUrl:o.agentGatewayUrl,agentKeys:agentKeys,logger:e.logger},a,t,r,n,()=>y()?.instanceId),e.logger.info?.("[beeos-claw] A2A tools registered (beeos_discover_agents, beeos_call_agent) via REST")}if(o.canvasEnabled){sharedCanvasState||(sharedCanvasState=new CanvasStateManager);const t=sharedCanvasState;if(o.agentGatewayUrl&&agentKeys){let r;t.setLogger(e.logger);{const e=o.agentGatewayUrl,t=agentKeys;r=async()=>{const r=await agentFetch(`${e}/api/v1/canvas/token`,t,{method:"POST",headers:{"content-type":"application/json"},body:"{}"});if(!r.ok){const e=await r.text().catch(()=>"");throw new Error(`Canvas token returned ${r.status}: ${e}`)}return r.json()}}const n=n=>{const a=new CanvasRelayClient({canvasRelayUrl:o.canvasRelayUrl,agentKeys:agentKeys,agentId:n.id,displayName:n.displayName,avatarUrl:n.avatarUrl,tokenProvider:r,onConnected:()=>p.flushPendingCanvasLinks(),onReconnect:()=>p.onRelayReconnected(),logger:e.logger});t.setRelayClient(a),t.setAgentId(n.id),p.wireRelayActionHandler(),a.connect(),e.logger.info?.(`[beeos-claw] Canvas Relay multiplexed client connected (agentId=${n.id}, name=${n.name??"none"})`)};e.registerService(createCanvasRelayService({getAgent:y,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=>n(e),getActiveSessionId:e=>p.getSessionIdForToolCall(e),getPlatformAgentId:e=>p.getPlatformAgentIdForToolCall(e),getGatewaySessionKey:e=>p.getGatewaySessionKeyForToolCall(e),waitForAgentSync:()=>sharedAgentMappings.waitForSynchronization()},i=new FormSchemaRegistry,s=buildCronSchemas(a);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(createRenderUiHandler(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 g=p.getResourceRenderer();if(g){generateActionTools(l,e,async(e,t)=>p.gatewayRequest(e,t),g,e.logger)}const d=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]),h=256,f=new Map;if("function"==typeof e.on){try{e.on("before_prompt_build",(e,t)=>{if(t?.sessionKey){if(f.size>=h&&!f.has(t.sessionKey)){const e=f.keys().next().value;void 0!==e&&f.delete(e)}f.set(t.sessionKey,t.channelId),rememberDeliveryWorkspace(t.sessionKey,t.workspaceDir)}const r=isThirdPartyChannel(a,{sessionKey:t?.sessionKey,channelId:t?.channelId});return t?.sessionKey||r?{appendSystemContext:buildAppendSystemContext({thirdParty:r,canvasSystemPrompt:`${CANVAS_PRESENTATION_GATE}\n\n${CANVAS_SYSTEM_PROMPT}`,toolRoutingHint:d})}:{appendSystemContext:d}}),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?f.get(t.sessionKey):void 0,o=isThirdPartyChannel(a,{sessionKey:t?.sessionKey,channelId:r}),n=canvasToolBlockReason({thirdParty:o,hasSession:Boolean(t?.sessionKey)});return n?{block:!0,blockReason:n}: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:n});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}`)}}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;const t=planPluginRegistration(e.registrationMode,_fullRuntimeRegistered);if("skip"!==t){_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 r=(t,r)=>{registerUploadTools(e,t,r),registerConnectorMcpProxy(e,t),registerArouterLatencyRouting(e),registerArouterMediaProviders(e)};if("capabilities"===t&&sharedPluginContext){if(cachedCapabilityTools.length>0){const t=resolveCapabilityToolReplay({currentRegisterTool:e.registerTool,wrappedRegisterTool:wrappedRegisterTool,originalRegisterTool:rawRegisterTool}),r=replayCachedPluginTools(r=>t.call(e,r),cachedCapabilityTools);return registerArouterLatencyRouting(e),registerArouterMediaProviders(e),void e.logger.info?.(`[beeos-claw] capability re-register mode=${e.registrationMode} tools_only count=${r}`)}const t={current:sharedAcpServer??null};return r(sharedPluginContext,t),registerServices(e,sharedPluginContext,t),void e.logger.info?.(`[beeos-claw] capability re-register mode=${e.registrationMode} capabilities_only`)}const o=initializePlugin(e);if(!o)return;const n={current:null};installUnhandledRejectionObserver(e,o.writeObs,n),ensureRegisterToolCache(e),cachedCapabilityTools.length=0,r(o,n),agentKeys&&o.cfg.agentGatewayUrl&&(e.on?e.on("before_agent_finalize",fileDeliveryFinalizeDecision):e.logger.warn?.("[file-delivery] OpenClaw plugin hooks unavailable; finalization check disabled")),registerServices(e,o,n),sharedPluginContext=o,marksFullRuntimeRegistered(e.registrationMode,t)&&(_fullRuntimeRegistered=!0),_pluginRegisteredAt=Date.now(),e.logger.info?.("[beeos-claw] Plugin registered successfully")}finally{_initializing=!1}}else e.logger.info?.(`[beeos-claw] skip re-register mode=${e.registrationMode??"full"} already_registered`)}};export default plugin;
@@ -1 +1 @@
1
- import{toMessagePart}from"../message-client-types.js";import{isUploadArtifactToolName,resolveToolArtifactLinks}from"../upload/tool-artifact-enrichment.js";import{sessionWorkspaceDir,takeFinalizeAttachments}from"../upload/delivery-ledger.js";import{resolveRuntimeToolArguments,resolveRuntimeToolCallId,resolveRuntimeToolName}from"./tool-envelope-metadata.js";import{extractSearchSources,mergeSearchSource,searchSourceProvider}from"./search-source-extractor.js";import{logChatLatency}from"../chat-latency.js";const STREAMING_SNAPSHOT_PUBLISH_INTERVAL_MS=200,isNonEmptyString=e=>"string"==typeof e&&e.length>0,isPlainRecord=e=>"object"==typeof e&&null!==e&&!Array.isArray(e);function pickRawResultFromPayload(e){if(void 0!==e.rawResult)return e.rawResult;if(void 0!==e.result)return e.result;if(void 0!==e.details)return e.details;if(void 0!==e.toolResult)return e.toolResult;if(isPlainRecord(e.channelData)){const t=e.channelData;if(void 0!==t.rawResult)return t.rawResult;if(void 0!==t.result)return t.result;if(void 0!==t.details)return t.details}}function asToolParams(e){if(e&&"object"==typeof e&&!Array.isArray(e))return e}const summarizeObservedToolError=e=>{if(null==e)return;if("string"==typeof e)return e.slice(0,180);if("object"!=typeof e)return String(e).slice(0,180);const t=e;for(const e of["error","message","blockReason","details","text"]){const r=t[e];if("string"==typeof r&&r.trim())return r.slice(0,180);if(isPlainRecord(r)&&"string"==typeof r.message&&r.message.trim())return r.message.slice(0,180)}try{const t=JSON.stringify(e);return t?t.slice(0,180):void 0}catch{return}};export function createImReplySink(e){const t=e.startedAtMs??Date.now();let r=!1;const n=new Map,s=new Set,o={text:""};let a="",i="",l=!1,d=!1;const u=new Set;let m;const c={receivedSnapshotCount:0,streamingPublishCount:0,terminalPublishCount:0},g=[];let p;const h=new Map,f=new Map,v=[],b=[],y=new Map,I=new Map;let _=0,S=1;const x=(e,t={})=>({schema_version:1,seq:e,...t}),k=new Set,$=new Set,q=t=>{t!==o.text&&(t.startsWith(o.text)?e.stream.appendBody(t.slice(o.text.length)):e.stream.setBody(t),o.text=t)},w=e=>{void 0===e.publishTimer&&(e.publishTimer=setTimeout(()=>{e.publishTimer=void 0,le("body_preview_flush",()=>{m===e&&(e=>{o.text!==e.targetBody&&(q(e.targetBody),e.streamingPublishCount+=1)})(e)})},200))},C=e=>{const t=m;t?(void 0!==t.publishTimer&&(clearTimeout(t.publishTimer),t.publishTimer=void 0),t.targetBody=e,o.text!==e&&(q(e),t.terminalPublishCount+=1),c.receivedSnapshotCount+=t.receivedSnapshotCount,c.streamingPublishCount+=t.streamingPublishCount,c.terminalPublishCount+=t.terminalPublishCount,m=void 0):q(e)},T=t=>{if(void 0!==t.partIndex)return;const r=_,n=S;e.stream.addPart(toMessagePart({type:"text",text:t.text,state:"done",_seq:n,data:x(n)})),t.partIndex=r,_+=1,S+=1},P=()=>{if(!d){d=!0;for(const e of g)T(e)}},E=e=>{const t={text:e};g.push(t),d&&T(t)},R=(t,r)=>{for(const n of t){const t=I.get(n.url);if(t){const r=mergeSearchSource(t,n);if(r.title===t.title&&r.snippet===t.snippet)continue;const s={...r,partIndex:t.partIndex,displaySeq:t.displaySeq,toolUseId:t.toolUseId};e.stream.replacePart(t.partIndex,toMessagePart({type:"source",url:s.url,...s.title?{title:s.title}:{},...s.snippet?{snippet:s.snippet}:{},tool_use_id:s.toolUseId,_seq:s.displaySeq,data:x(s.displaySeq)})),I.set(n.url,s);continue}const s={...n,partIndex:_,displaySeq:S,toolUseId:r};e.stream.addPart(toMessagePart({type:"source",url:n.url,...n.title?{title:n.title}:{},...n.snippet?{snippet:n.snippet}:{},tool_use_id:r,_seq:s.displaySeq,data:x(s.displaySeq)})),I.set(n.url,s),_+=1,S+=1,oe.source+=1}},M=(e,t,r,n)=>toMessagePart({type:"thinking",text:t,state:r,_seq:e.displaySeq,_started_at_ms:e.startedAtMs,...void 0!==n?{_duration_ms:n}:{},data:x(e.displaySeq,{started_at_ms:e.startedAtMs,...void 0!==n?{duration_ms:n}:{}})}),O=t=>{void 0===t.publishTimer&&(t.publishTimer=setTimeout(()=>{t.publishTimer=void 0,le("reasoning_snapshot_flush",()=>{p===t&&(t=>{t.publishedText!==t.text&&(e.stream.replacePart(t.partIndex,M(t,t.text,"streaming")),t.publishedText=t.text,t.streamingPublishCount+=1)})(t)})},200))},A=()=>{const r=p;if(!r)return;void 0!==r.publishTimer&&(clearTimeout(r.publishTimer),r.publishTimer=void 0);const n=Math.max(0,Math.round(performance.now()-r.startedAtMonotonicMs));e.stream.replacePart(r.partIndex,M(r,r.text,"done",n)),p=void 0,logChatLatency(e.logger,"claw.reasoning.settled",e.requestId,t,{reasoning_duration_ms:n,reasoning_chars:r.text.length,reasoning_snapshot_count:r.receivedSnapshotCount,reasoning_streaming_publish_count:r.streamingPublishCount,reasoning_coalesced_snapshot_count:Math.max(0,r.receivedSnapshotCount-r.streamingPublishCount),reasoning_publish_interval_ms:200})},F=e=>{const t=v.indexOf(e);t>=0&&v.splice(t,1)},N=e=>{const t=e?v.filter(t=>h.get(t)?.name===e):v;return 1===t.length?t[0]:void 0},U=e=>{const t=b.map((e,t)=>({hint:e,index:t})).filter(({hint:t})=>!e||t.name===e);if(1!==t.length)return;const[{hint:r,index:n}]=t;return b.splice(n,1),r},j=(e,t)=>{if(f.set(e,t),e===t)return;const r=y.get(e);if(!r)return;const n=z(t);Q(n,r),y.delete(e);const s=h.get(t);s&&(X(s,n),y.delete(t))},L=e=>f.get(e)??e,B=e=>null!=e&&("object"!=typeof e||(Array.isArray(e)?e.length>0:Object.keys(e).length>0)),z=e=>{let t=y.get(e);return t||(t={},y.set(e,t)),t},D=(e,t)=>{if(!e?.length&&!t?.length)return;const r=[],n=new Map;for(const s of[...e??[],...t??[]]){const e=n.get(s.url);void 0===e?(n.set(s.url,r.length),r.push(s)):r[e]=mergeSearchSource(r[e],s)}return r},Q=(e,t)=>{e.name??=t.name,e.arguments??=t.arguments,t.toolStartObserved&&(e.toolStartObserved=!0),t.itemEventObserved&&(e.itemEventObserved=!0),t.progress?.length&&(e.progress=[...e.progress??[],...t.progress]),e.sources=D(e.sources,t.sources)},W=(t,r,n)=>{const s="tool"===t.name&&"tool"!==r?r:t.name,o=!B(t.arguments)&&B(n)?n:t.arguments;s===t.name&&o===t.arguments||(e.stream.replacePart(t.partIndex,toMessagePart({type:"tool_use",id:t.id,name:s,arguments:o,state:t.state,_seq:t.displaySeq,data:x(t.displaySeq)})),t.name=s,t.arguments=o)},J=(t,r,n,s)=>{const o=h.get(t);if(o)return W(o,r,n),s&&!v.includes(t)&&"streaming"===o.state&&v.push(t),o;P();const a=y.get(t),i="tool"!==r?r:a?.name&&"tool"!==a.name?a.name:r,l=B(n)?n:a?.arguments??n,d=((t,r,n)=>{const s=_,o=S;return e.stream.addPart(toMessagePart({type:"tool_use",id:t,name:r,arguments:n,state:"streaming",_seq:o,data:x(o)})),_+=1,S+=1,{partIndex:s,displaySeq:o}})(t,i,l),u={id:t,name:i,arguments:l,partIndex:d.partIndex,displaySeq:d.displaySeq,state:"streaming",itemEventObserved:!0===a?.itemEventObserved,toolStartObserved:!0===a?.toolStartObserved};return h.set(t,u),(s||u.toolStartObserved||u.itemEventObserved)&&(v.includes(t)||"streaming"!==u.state||v.push(t)),a&&X(u,a),y.delete(t),u},H=(e,t)=>{const r=(e=>{const t=f.get(e);return t?h.get(t):h.get(e)})(e);if(r)return void 0===t.name&&void 0===t.arguments||W(r,t.name??r.name,t.arguments??r.arguments),t.toolStartObserved&&(r.toolStartObserved=!0),t.itemEventObserved&&(r.itemEventObserved=!0),(t.pending||t.toolStartObserved||t.itemEventObserved)&&!v.includes(r.id)&&"streaming"===r.state&&v.push(r.id),r;const n=z(e);void 0!==t.name&&(n.name=t.name),void 0!==t.arguments&&(n.arguments=t.arguments),t.toolStartObserved&&(n.toolStartObserved=!0),t.itemEventObserved&&(n.itemEventObserved=!0)},K=t=>{"done"!==t.state&&(e.stream.replacePart(t.partIndex,toMessagePart({type:"tool_use",id:t.id,name:t.name,arguments:t.arguments,state:"done",_seq:t.displaySeq,data:x(t.displaySeq)})),t.state="done")},G=e=>{if(null===e||"object"!=typeof e)return JSON.stringify(e)??String(e);if(Array.isArray(e))return`[${e.map(G).join(",")}]`;return`{${Object.entries(e).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${JSON.stringify(e)}:${G(t)}`).join(",")}}`},V=(t,r,n)=>{const s=`${n?"1":"0"}:${G(r)}`;if(t.progressSignature===s)return;const o=toMessagePart({type:"custom",kind:"tool_progress",data:{tool_use_id:t.id,content:r,...n?{is_error:!0}:{}}});if(void 0===t.progressPartIndex){const r=_;return e.stream.addPart(o),t.progressPartIndex=r,t.progressSignature=s,void(_+=1)}e.stream.replacePart(t.progressPartIndex,o),t.progressSignature=s},X=(e,t)=>{if(t.progress?.length){for(const r of t.progress)V(e,r.content,r.isError);K(e),F(e.id)}t.sources?.length&&R(t.sources,e.id)},Y=e=>[...new Set([e.mediaUrl,...e.mediaUrls??[]].filter(e=>isNonEmptyString(e)).map(e=>e.trim()).filter(Boolean))],Z=(e,t=[])=>{const r=[...new Set([...Y(e),...t])];return isNonEmptyString(e.text)&&r.length>0?{text:e.text,media_urls:r}:isNonEmptyString(e.text)?e.text:1===r.length?r[0]:r.length>1?{media_urls:r}:!0===e.isError?"Tool execution failed.":""},ee=t=>{for(const r of t)e.stream.addPart(toMessagePart({type:"resource_link",uri:r.uri,name:r.name,...r.mimeType?{mimeType:r.mimeType}:{}})),_+=1},te=t=>{k.add(t);const r=()=>{k.delete(t)};e.onCallbackFailure?t.then(r,r):t.finally(r)},re=(t,r)=>{if(t.durableUploadFilesEmitted)return;e.logger.info?.(`[im-sink] schedule tool artifact enrichment requestId=${e.requestId} toolUseId=${t.id} name=${t.name}`);const n=pickRawResultFromPayload(r),s=(async()=>{let s=[];try{s=await resolveToolArtifactLinks({toolCallId:t.id,toolName:t.name,rawResult:n,rawText:"string"==typeof r.text?r.text:void 0,params:asToolParams(t.arguments),cwd:sessionWorkspaceDir(e.sessionKey),payloadMediaUrls:Y(r)})}catch(r){const n=r instanceof Error?r.message:String(r);if(e.logger.warn?.(`[im-sink] resolveToolArtifactLinks failed requestId=${e.requestId} toolUseId=${t.id} error=${n}`),e.onCallbackFailure?.(r),e.onCallbackFailure)throw r;return}0!==s.length?(e.logger.info?.(`[im-sink] tool artifact enrichment resolved ${s.length} link(s) requestId=${e.requestId} toolUseId=${t.id}`),await new Promise((n,o)=>{const a=e.callbackQueue.enqueueSync(()=>{try{if(e.abortSignal.aborted||e.stream.isTerminated)return;const n=s.map(e=>e.uri);V(t,Z(r,n),!0===r.isError),((t,r,n)=>{0===r.length||t.durableUploadFilesEmitted||(t.durableUploadFilesEmitted=!0,e.stream.appendToolResult(t.id,r.map(e=>({type:"resource_link",uri:e.uri,name:e.name,...e.mimeType?{mimeType:e.mimeType}:{}})),n),_+=1,ee(r))})(t,s,!0===r.isError)}catch(r){const n=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] tool artifact enrichment apply failed requestId=${e.requestId} toolUseId=${t.id} error=${n}`),e.onCallbackFailure?.(r),e.onCallbackFailure&&o(r)}finally{n()}});!1===a&&e.onCallbackFailure&&e.callbackQueue.waitForIdle().then(n,o)})):e.logger.debug?.(`[im-sink] tool artifact enrichment found no links requestId=${e.requestId} toolUseId=${t.id} name=${t.name}`)})().catch(r=>{const n=r instanceof Error?r.message:String(r);if(e.logger.warn?.(`[im-sink] tool artifact enrichment failed requestId=${e.requestId} toolUseId=${t.id} error=${n}`),e.onCallbackFailure?.(r),e.onCallbackFailure)throw r});te(s)},ne=(e,t,r)=>{const n=f.get(e);if(n)return H(n,{name:t,arguments:r});const s=H(e,{name:t,arguments:r});if(s)return s;const o=N(t);if(o)return j(e,o),H(o,{name:t,arguments:r});H(e,{name:t,arguments:r})},se=(e,t)=>{const r=f.get(e);if(r)return H(r,{name:t,itemEventObserved:!0,pending:!0});const n=H(e,{name:t,itemEventObserved:!0,pending:!0});if(n)return n;const s=(e=>{const t=v.filter(t=>{const r=h.get(t);return!(void 0===r||e&&r.name!==e||r.itemEventObserved)});return 1===t.length?t[0]:void 0})(t);if(s)return j(e,s),H(s,{name:t,itemEventObserved:!0,pending:!0});const o=U(t);H(e,{name:t,arguments:o?.arguments,itemEventObserved:!0,pending:!0})},oe={tool:0,block:0,final:0,source:0};let ae,ie=!1;const le=(t,r)=>{e.callbackQueue.enqueueSync(()=>{if((t=>e.abortSignal.aborted?(e.logger.debug?.(`[im-sink] ${t} ignored after abort requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1):e.stream.isTerminated?(e.logger.debug?.(`[im-sink] ${t} ignored after stream_terminated requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1):!ie||(e.logger.debug?.(`[im-sink] ${t} ignored after mark_complete requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1))(t))try{r()}catch(r){const n=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] ${t} mapping failed requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId} error=${n}`),e.onCallbackFailure?.(r)}})};return{dispatcher:{sendToolResult:t=>(le("tool_progress",()=>{const r=resolveRuntimeToolCallId(t),n=resolveRuntimeToolName(t),s=resolveRuntimeToolArguments(t),o=Z(t),a=!0===t.isError;let i;if(r){if(i=ne(r,n,s),!i){const e=z(r);return n&&(e.name=n),B(s)&&(e.arguments=s),e.progress=[...e.progress??[],{content:o,isError:a}],void(oe.tool+=1)}}else{const t=n?N(n):N();if(!t)return U(n),void e.logger.debug?.(`[im-sink] unattributed tool progress ignored requestId=${e.requestId} channel=${e.channelId} tool=${n??"unknown"} pending=${v.length}`);i=H(t,{name:n,arguments:s})}i&&(oe.tool+=1,V(i,o,a),K(i),F(i.id),re(i,t))}),!0),sendBlockReply:e=>(le("block_reply",()=>{oe.block+=1,isNonEmptyString(e.text)&&(ae=!0!==e.isError?void 0:e.text)}),!0),sendFinalReply:t=>(le("final_reply",()=>{var r;(oe.final+=1,!0!==t.isError)?((t=>{const r=Y(t).filter(e=>!$.has(e));if(0===r.length)return;for(const e of r)$.add(e);const n=(async()=>{let t=[];try{t=await resolveToolArtifactLinks({toolCallId:`final:${e.runId??e.requestId}`,toolName:"final_reply_media",payloadMediaUrls:r})}catch(t){for(const e of r)$.delete(e);if(e.logger.warn?.(`[im-sink] final media enrichment failed requestId=${e.requestId} error=${t instanceof Error?t.message:String(t)}`),e.onCallbackFailure?.(t),e.onCallbackFailure)throw t;return}if(0!==t.length)await new Promise((r,n)=>{!1===e.callbackQueue.enqueueSync(()=>{try{if(e.abortSignal.aborted||e.stream.isTerminated)return;ee(t)}catch(t){e.logger.warn?.(`[im-sink] final media enrichment apply failed requestId=${e.requestId} error=${t instanceof Error?t.message:String(t)}`),e.onCallbackFailure?.(t),e.onCallbackFailure&&n(t)}finally{r()}})&&e.onCallbackFailure&&e.callbackQueue.waitForIdle().then(r,n)});else for(const e of r)$.delete(e)})();te(n)})(t),isNonEmptyString(t.text)&&(ae=void 0,l||(r=t.text,i="",a+=r,C(a),E(r),l=!0))):ae=t.text}),!0),waitForIdle:async()=>{for(let t=0;(e.onCallbackFailure||t<16)&&(await e.callbackQueue.waitForIdle(),0!==k.size);t++)e.onCallbackFailure?await Promise.all([...k]):await Promise.allSettled([...k]);await e.callbackQueue.waitForIdle();const t=takeFinalizeAttachments(e.sessionKey);t.length>0&&!e.abortSignal.aborted&&!e.stream.isTerminated&&ee(t)},getQueuedCounts:()=>({tool:oe.tool,block:oe.block,final:oe.final}),getAccumulatedBody:()=>o.text,getTerminalErrorText:()=>ae,markComplete:r=>{A(),(b.length>0||y.size>0)&&e.logger.debug?.(`[im-sink] dropping uncommitted lifecycle tool signals requestId=${e.requestId} legacy_hints=${b.length} buffered=${y.size}`),i="",C(a),c.receivedSnapshotCount>0&&logChatLatency(e.logger,"claw.text_preview.settled",e.requestId,t,{text_preview_snapshot_count:c.receivedSnapshotCount,text_preview_streaming_publish_count:c.streamingPublishCount,text_preview_terminal_publish_count:c.terminalPublishCount,text_preview_coalesced_snapshot_count:Math.max(0,c.receivedSnapshotCount-c.streamingPublishCount-c.terminalPublishCount),text_preview_publish_interval_ms:200});for(const t of h.values())try{"success"===r&&isUploadArtifactToolName(t.name)&&!t.durableUploadFilesEmitted&&re(t,{toolCallId:t.id,toolName:t.name}),"success"===r&&K(t),F(t.id)}catch(r){const n=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] tool finalization failed requestId=${e.requestId} toolUseId=${t.id} error=${n}`)}b.length=0,y.clear(),ie=!0}},replyOptions:{...e.runId?{runId:e.runId}:{},abortSignal:e.abortSignal,disableBlockStreaming:!0,onAgentRunStart:r=>{e.onAgentRunStart?.(r),logChatLatency(e.logger,"claw.runtime.run_started",e.requestId,t),e.logger.info?.(`[im-sink] run_start requestId=${e.requestId} runId=${r} channel=${e.channelId} in_reply_to=${e.inboundMessageId} origin=${e.origin??"im"}`)},onPartialReply:n=>{le("partial",()=>{"string"==typeof n.text&&(!r&&n.text.length>0&&(r=!0,logChatLatency(e.logger,"claw.model.first_delta",e.requestId,t)),i=n.text,(e=>{const t=m;if(!t){if(o.text===e)return;return q(e),void(m={targetBody:e,receivedSnapshotCount:1,streamingPublishCount:1,terminalPublishCount:0})}t.targetBody!==e&&(t.targetBody=e,t.receivedSnapshotCount+=1,w(t))})(a+i))})},onReasoningStream:t=>{le("reasoning",()=>{if(!isNonEmptyString(t.text))return;const r=t.text,n=p??(t=>{P();const r={partIndex:_,displaySeq:S,text:t,publishedText:t,receivedSnapshotCount:1,streamingPublishCount:1,startedAtMs:Date.now(),startedAtMonotonicMs:performance.now()};return e.stream.addPart(M(r,t,"streaming")),_+=1,S+=1,p=r,r})(r);r!==n.text&&(n.text.startsWith(r)||(n.text=r,n.receivedSnapshotCount+=1,O(n)))})},onReasoningEnd:()=>{le("reasoning_end",()=>{A()})},onAssistantMessageStart:()=>{le("assistant_message_start",()=>{i="",l=!1,C(a),e.logger.debug?.(`[im-sink] assistant_message_start requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`)})},onToolStart:r=>{le("tool_start",()=>{const s="string"==typeof r.phase?r.phase:"start",o=resolveRuntimeToolName(r)??"tool",a=resolveRuntimeToolCallId(r),i=resolveRuntimeToolArguments(r);if("update"===s)return void(a&&H(L(a),{name:o,arguments:i,pending:!0}));if(a&&n.set(a,Date.now()),logChatLatency(e.logger,"claw.tool.start",e.requestId,t,{tool:o}),a){H(a,{name:o,arguments:i,toolStartObserved:!0,pending:!0});const e=N(o);return void(e&&e!==a&&!f.has(a)&&(j(a,e),H(e,{name:o,arguments:i,toolStartObserved:!0,pending:!0})))}const l=(d=o,v.map(e=>h.get(e)).filter(e=>void 0!==e&&(!d||e.name===d)&&e.itemEventObserved));var d;if(1===l.length)return void H(l[0].id,{name:o,arguments:i,toolStartObserved:!0,pending:!0});if(l.length>1)return void e.logger.debug?.(`[im-sink] ambiguous id-less tool start ignored requestId=${e.requestId} channel=${e.channelId} tool=${o} candidates=${l.length}`);const u=[...y.entries()].filter(([,e])=>!e.name||e.name===o||"tool"===e.name);1!==u.length?b.push({name:o,arguments:i}):H(u[0][0],{name:o,arguments:i,toolStartObserved:!0,pending:!0})})},onItemEvent:e=>{le("item_event",()=>{const t="string"==typeof e.kind?e.kind.toLowerCase():"";if(t&&"tool"!==t)return;const r="string"==typeof e.phase?e.phase.toLowerCase():"update",n=resolveRuntimeToolCallId(e)??("string"==typeof e.itemId&&e.itemId.trim()?e.itemId.trim():void 0),s=resolveRuntimeToolName(e)??("string"==typeof e.title&&e.title.trim()?e.title.trim():void 0);n&&s&&("update"!==r?se(n,s):H(L(n),{name:s,itemEventObserved:!0,pending:!0}))})}},commitAssistantMessage:e=>{le("assistant_message_commit",()=>{if(u.has(e.key))return;u.add(e.key),l=!0,ae=void 0,i="";const t=e.segments.filter(e=>"text"===e.type).map(e=>e.text).join("");a+=t,C(a);for(const t of e.segments)"text"!==t.type?J(t.id,t.name,t.arguments,!0):E(t.text)})},observeToolResult:r=>{le("tool_result_observation",()=>{const o=r.toolCallId.trim(),a=r.toolName.trim();if(!o||!a)return;if(!s.has(o)){s.add(o);const i=n.get(o);logChatLatency(e.logger,"claw.tool.result",e.requestId,t,{tool:a,tool_elapsed_ms:void 0===i?void 0:Math.max(0,Date.now()-i),outcome:r.isError?"error":"success",...r.isError?{error:summarizeObservedToolError(r.rawResult)??"error"}:{}})}const i=searchSourceProvider(r.rawResult)??"unknown";let l=0;try{const t=extractSearchSources({toolName:a,rawResult:r.rawResult,isError:r.isError});if(l=t.length,0===l)return;const n=ne(o,a);if(n)R(t,n.id);else{const e=z(L(o));e.name??=a,e.sources=D(e.sources,t)}e.logger.debug?.(`[im-sink] search source projection requestId=${e.requestId} tool=${a} provider=${i} source_count=${l}`)}catch{e.logger.warn?.(`[im-sink] search source projection ignored requestId=${e.requestId} tool=${a} provider=${i} source_count=${l}`)}})},getSourceCount:()=>oe.source}}
1
+ import{toMessagePart}from"../message-client-types.js";import{isUploadArtifactToolName,resolveToolArtifactLinks}from"../upload/tool-artifact-enrichment.js";import{sessionWorkspaceDir,takeFinalizeAttachments}from"../upload/delivery-ledger.js";import{resolveRuntimeToolArguments,resolveRuntimeToolCallId,resolveRuntimeToolName}from"./tool-envelope-metadata.js";import{extractSearchSources,mergeSearchSource,searchSourceProvider}from"./search-source-extractor.js";import{logChatLatency}from"../chat-latency.js";const STREAMING_SNAPSHOT_PUBLISH_INTERVAL_MS=200,isNonEmptyString=e=>"string"==typeof e&&e.length>0,isPlainRecord=e=>"object"==typeof e&&null!==e&&!Array.isArray(e);function pickRawResultFromPayload(e){if(void 0!==e.rawResult)return e.rawResult;if(void 0!==e.result)return e.result;if(void 0!==e.details)return e.details;if(void 0!==e.toolResult)return e.toolResult;if(isPlainRecord(e.channelData)){const t=e.channelData;if(void 0!==t.rawResult)return t.rawResult;if(void 0!==t.result)return t.result;if(void 0!==t.details)return t.details}}function asToolParams(e){if(e&&"object"==typeof e&&!Array.isArray(e))return e}const summarizeObservedToolError=e=>{if(null==e)return;if("string"==typeof e)return e.slice(0,180);if("object"!=typeof e)return String(e).slice(0,180);const t=e;for(const e of["error","message","blockReason","details","text"]){const r=t[e];if("string"==typeof r&&r.trim())return r.slice(0,180);if(isPlainRecord(r)&&"string"==typeof r.message&&r.message.trim())return r.message.slice(0,180)}try{const t=JSON.stringify(e);return t?t.slice(0,180):void 0}catch{return}},observedToolResultText=e=>{if(!isPlainRecord(e)||!Array.isArray(e.content))return;const t=e.content.filter(e=>isPlainRecord(e)&&"text"===e.type&&"string"==typeof e.text).map(e=>e.text.trim()).filter(Boolean);return t.length>0?t.join("\n"):void 0};export function createImReplySink(e){const t=e.startedAtMs??Date.now();let r=!1;const s=new Map,n=new Set,o={text:""};let a="",i="",l=!1,d=!1;const u=new Set;let c;const m={receivedSnapshotCount:0,streamingPublishCount:0,terminalPublishCount:0},g=[];let p;const f=new Map,h=new Map,v=[],b=[],y=new Map,I=new Map;let _=0,S=1;const x=(e,t={})=>({schema_version:1,seq:e,...t}),k=new Set,$=new Set,q=t=>{t!==o.text&&(t.startsWith(o.text)?e.stream.appendBody(t.slice(o.text.length)):e.stream.setBody(t),o.text=t)},w=e=>{void 0===e.publishTimer&&(e.publishTimer=setTimeout(()=>{e.publishTimer=void 0,le("body_preview_flush",()=>{c===e&&(e=>{o.text!==e.targetBody&&(q(e.targetBody),e.streamingPublishCount+=1)})(e)})},200))},C=e=>{const t=c;t?(void 0!==t.publishTimer&&(clearTimeout(t.publishTimer),t.publishTimer=void 0),t.targetBody=e,o.text!==e&&(q(e),t.terminalPublishCount+=1),m.receivedSnapshotCount+=t.receivedSnapshotCount,m.streamingPublishCount+=t.streamingPublishCount,m.terminalPublishCount+=t.terminalPublishCount,c=void 0):q(e)},E=t=>{if(void 0!==t.partIndex)return;const r=_,s=S;e.stream.addPart(toMessagePart({type:"text",text:t.text,state:"done",_seq:s,data:x(s)})),t.partIndex=r,_+=1,S+=1},T=()=>{if(!d){d=!0;for(const e of g)E(e)}},P=e=>{const t={text:e};g.push(t),d&&E(t)},R=(t,r)=>{for(const s of t){const t=I.get(s.url);if(t){const r=mergeSearchSource(t,s);if(r.title===t.title&&r.snippet===t.snippet)continue;const n={...r,partIndex:t.partIndex,displaySeq:t.displaySeq,toolUseId:t.toolUseId};e.stream.replacePart(t.partIndex,toMessagePart({type:"source",url:n.url,...n.title?{title:n.title}:{},...n.snippet?{snippet:n.snippet}:{},tool_use_id:n.toolUseId,_seq:n.displaySeq,data:x(n.displaySeq)})),I.set(s.url,n);continue}const n={...s,partIndex:_,displaySeq:S,toolUseId:r};e.stream.addPart(toMessagePart({type:"source",url:s.url,...s.title?{title:s.title}:{},...s.snippet?{snippet:s.snippet}:{},tool_use_id:r,_seq:n.displaySeq,data:x(n.displaySeq)})),I.set(s.url,n),_+=1,S+=1,oe.source+=1}},M=(e,t,r,s)=>toMessagePart({type:"thinking",text:t,state:r,_seq:e.displaySeq,_started_at_ms:e.startedAtMs,...void 0!==s?{_duration_ms:s}:{},data:x(e.displaySeq,{started_at_ms:e.startedAtMs,...void 0!==s?{duration_ms:s}:{}})}),O=t=>{void 0===t.publishTimer&&(t.publishTimer=setTimeout(()=>{t.publishTimer=void 0,le("reasoning_snapshot_flush",()=>{p===t&&(t=>{t.publishedText!==t.text&&(e.stream.replacePart(t.partIndex,M(t,t.text,"streaming")),t.publishedText=t.text,t.streamingPublishCount+=1)})(t)})},200))},A=()=>{const r=p;if(!r)return;void 0!==r.publishTimer&&(clearTimeout(r.publishTimer),r.publishTimer=void 0);const s=Math.max(0,Math.round(performance.now()-r.startedAtMonotonicMs));e.stream.replacePart(r.partIndex,M(r,r.text,"done",s)),p=void 0,logChatLatency(e.logger,"claw.reasoning.settled",e.requestId,t,{reasoning_duration_ms:s,reasoning_chars:r.text.length,reasoning_snapshot_count:r.receivedSnapshotCount,reasoning_streaming_publish_count:r.streamingPublishCount,reasoning_coalesced_snapshot_count:Math.max(0,r.receivedSnapshotCount-r.streamingPublishCount),reasoning_publish_interval_ms:200})},F=e=>{const t=v.indexOf(e);t>=0&&v.splice(t,1)},N=e=>{const t=e?v.filter(t=>f.get(t)?.name===e):v;return 1===t.length?t[0]:void 0},U=e=>{const t=b.map((e,t)=>({hint:e,index:t})).filter(({hint:t})=>!e||t.name===e);if(1!==t.length)return;const[{hint:r,index:s}]=t;return b.splice(s,1),r},j=(e,t)=>{if(h.set(e,t),e===t)return;const r=y.get(e);if(!r)return;const s=z(t);Q(s,r),y.delete(e);const n=f.get(t);n&&(X(n,s),y.delete(t))},L=e=>h.get(e)??e,B=e=>null!=e&&("object"!=typeof e||(Array.isArray(e)?e.length>0:Object.keys(e).length>0)),z=e=>{let t=y.get(e);return t||(t={},y.set(e,t)),t},D=(e,t)=>{if(!e?.length&&!t?.length)return;const r=[],s=new Map;for(const n of[...e??[],...t??[]]){const e=s.get(n.url);void 0===e?(s.set(n.url,r.length),r.push(n)):r[e]=mergeSearchSource(r[e],n)}return r},Q=(e,t)=>{e.name??=t.name,e.arguments??=t.arguments,t.toolStartObserved&&(e.toolStartObserved=!0),t.itemEventObserved&&(e.itemEventObserved=!0),t.progress?.length&&(e.progress=[...e.progress??[],...t.progress]),e.observedResult??=t.observedResult,e.sources=D(e.sources,t.sources)},W=(t,r,s)=>{const n="tool"===t.name&&"tool"!==r?r:t.name,o=!B(t.arguments)&&B(s)?s:t.arguments;n===t.name&&o===t.arguments||(e.stream.replacePart(t.partIndex,toMessagePart({type:"tool_use",id:t.id,name:n,arguments:o,state:t.state,_seq:t.displaySeq,data:x(t.displaySeq)})),t.name=n,t.arguments=o)},J=(t,r,s,n)=>{const o=f.get(t);if(o)return W(o,r,s),n&&!v.includes(t)&&"streaming"===o.state&&v.push(t),o;T();const a=y.get(t),i="tool"!==r?r:a?.name&&"tool"!==a.name?a.name:r,l=B(s)?s:a?.arguments??s,d=((t,r,s)=>{const n=_,o=S;return e.stream.addPart(toMessagePart({type:"tool_use",id:t,name:r,arguments:s,state:"streaming",_seq:o,data:x(o)})),_+=1,S+=1,{partIndex:n,displaySeq:o}})(t,i,l),u={id:t,name:i,arguments:l,partIndex:d.partIndex,displaySeq:d.displaySeq,state:"streaming",itemEventObserved:!0===a?.itemEventObserved,toolStartObserved:!0===a?.toolStartObserved};return f.set(t,u),(n||u.toolStartObserved||u.itemEventObserved)&&(v.includes(t)||"streaming"!==u.state||v.push(t)),a&&X(u,a),y.delete(t),u},H=(e,t)=>{const r=(e=>{const t=h.get(e);return t?f.get(t):f.get(e)})(e);if(r)return void 0===t.name&&void 0===t.arguments||W(r,t.name??r.name,t.arguments??r.arguments),t.toolStartObserved&&(r.toolStartObserved=!0),t.itemEventObserved&&(r.itemEventObserved=!0),(t.pending||t.toolStartObserved||t.itemEventObserved)&&!v.includes(r.id)&&"streaming"===r.state&&v.push(r.id),r;const s=z(e);void 0!==t.name&&(s.name=t.name),void 0!==t.arguments&&(s.arguments=t.arguments),t.toolStartObserved&&(s.toolStartObserved=!0),t.itemEventObserved&&(s.itemEventObserved=!0)},K=t=>{"done"!==t.state&&(e.stream.replacePart(t.partIndex,toMessagePart({type:"tool_use",id:t.id,name:t.name,arguments:t.arguments,state:"done",_seq:t.displaySeq,data:x(t.displaySeq)})),t.state="done")},G=e=>{if(null===e||"object"!=typeof e)return JSON.stringify(e)??String(e);if(Array.isArray(e))return`[${e.map(G).join(",")}]`;return`{${Object.entries(e).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${JSON.stringify(e)}:${G(t)}`).join(",")}}`},V=(t,r,s)=>{const n=`${s?"1":"0"}:${G(r)}`;if(t.progressSignature===n)return;const o=toMessagePart({type:"custom",kind:"tool_progress",data:{tool_use_id:t.id,content:r,...s?{is_error:!0}:{}}});if(void 0===t.progressPartIndex){const r=_;return e.stream.addPart(o),t.progressPartIndex=r,t.progressSignature=n,void(_+=1)}e.stream.replacePart(t.progressPartIndex,o),t.progressSignature=n},X=(e,t)=>{if(t.progress?.length)for(const r of t.progress)V(e,r.content,r.isError);t.observedResult&&(V(e,t.observedResult.content,t.observedResult.isError),e.observedResult=t.observedResult),(t.progress?.length||t.observedResult)&&(K(e),F(e.id)),t.sources?.length&&R(t.sources,e.id)},Y=e=>[...new Set([e.mediaUrl,...e.mediaUrls??[]].filter(e=>isNonEmptyString(e)).map(e=>e.trim()).filter(Boolean))],Z=(e,t=[])=>{const r=[...new Set([...Y(e),...t])];return isNonEmptyString(e.text)&&r.length>0?{text:e.text,media_urls:r}:isNonEmptyString(e.text)?e.text:1===r.length?r[0]:r.length>1?{media_urls:r}:!0===e.isError?"Tool execution failed.":""},ee=t=>{for(const r of t)e.stream.addPart(toMessagePart({type:"resource_link",uri:r.uri,name:r.name,...r.mimeType?{mimeType:r.mimeType}:{}})),_+=1},te=t=>{k.add(t);const r=()=>{k.delete(t)};e.onCallbackFailure?t.then(r,r):t.finally(r)},re=(t,r)=>{if(t.durableUploadFilesEmitted)return;e.logger.info?.(`[im-sink] schedule tool artifact enrichment requestId=${e.requestId} toolUseId=${t.id} name=${t.name}`);const s=pickRawResultFromPayload(r),n=(async()=>{let n=[];try{n=await resolveToolArtifactLinks({toolCallId:t.id,toolName:t.name,rawResult:s,rawText:"string"==typeof r.text?r.text:void 0,params:asToolParams(t.arguments),cwd:sessionWorkspaceDir(e.sessionKey),payloadMediaUrls:Y(r)})}catch(r){const s=r instanceof Error?r.message:String(r);if(e.logger.warn?.(`[im-sink] resolveToolArtifactLinks failed requestId=${e.requestId} toolUseId=${t.id} error=${s}`),e.onCallbackFailure?.(r),e.onCallbackFailure)throw r;return}0!==n.length?(e.logger.info?.(`[im-sink] tool artifact enrichment resolved ${n.length} link(s) requestId=${e.requestId} toolUseId=${t.id}`),await new Promise((s,o)=>{!1===e.callbackQueue.enqueueSync(()=>{try{if(e.abortSignal.aborted||e.stream.isTerminated)return;const s=n.map(e=>e.uri);t.artifactMediaUrls=s;const o=t.observedResult;V(t,Z(o?{text:o.content,isError:o.isError}:r,s),o?.isError??!0===r.isError),((t,r,s)=>{0===r.length||t.durableUploadFilesEmitted||(t.durableUploadFilesEmitted=!0,e.stream.appendToolResult(t.id,r.map(e=>({type:"resource_link",uri:e.uri,name:e.name,...e.mimeType?{mimeType:e.mimeType}:{}})),s),_+=1,ee(r))})(t,n,o?.isError??!0===r.isError)}catch(r){const s=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] tool artifact enrichment apply failed requestId=${e.requestId} toolUseId=${t.id} error=${s}`),e.onCallbackFailure?.(r),e.onCallbackFailure&&o(r)}finally{s()}})&&e.onCallbackFailure&&e.callbackQueue.waitForIdle().then(s,o)})):e.logger.debug?.(`[im-sink] tool artifact enrichment found no links requestId=${e.requestId} toolUseId=${t.id} name=${t.name}`)})().catch(r=>{const s=r instanceof Error?r.message:String(r);if(e.logger.warn?.(`[im-sink] tool artifact enrichment failed requestId=${e.requestId} toolUseId=${t.id} error=${s}`),e.onCallbackFailure?.(r),e.onCallbackFailure)throw r});te(n)},se=(e,t,r)=>{const s=h.get(e);if(s)return H(s,{name:t,arguments:r});const n=H(e,{name:t,arguments:r});if(n)return n;const o=N(t);if(o)return j(e,o),H(o,{name:t,arguments:r});H(e,{name:t,arguments:r})},ne=(e,t)=>{const r=h.get(e);if(r)return H(r,{name:t,itemEventObserved:!0,pending:!0});const s=H(e,{name:t,itemEventObserved:!0,pending:!0});if(s)return s;const n=(e=>{const t=v.filter(t=>{const r=f.get(t);return!(void 0===r||e&&r.name!==e||r.itemEventObserved)});return 1===t.length?t[0]:void 0})(t);if(n)return j(e,n),H(n,{name:t,itemEventObserved:!0,pending:!0});const o=U(t);H(e,{name:t,arguments:o?.arguments,itemEventObserved:!0,pending:!0})},oe={tool:0,block:0,final:0,source:0};let ae,ie=!1;const le=(t,r)=>{e.callbackQueue.enqueueSync(()=>{if((t=>e.abortSignal.aborted?(e.logger.debug?.(`[im-sink] ${t} ignored after abort requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1):e.stream.isTerminated?(e.logger.debug?.(`[im-sink] ${t} ignored after stream_terminated requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1):!ie||(e.logger.debug?.(`[im-sink] ${t} ignored after mark_complete requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1))(t))try{r()}catch(r){const s=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] ${t} mapping failed requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId} error=${s}`),e.onCallbackFailure?.(r)}})};return{dispatcher:{sendToolResult:t=>(le("tool_progress",()=>{const r=resolveRuntimeToolCallId(t),s=resolveRuntimeToolName(t),n=resolveRuntimeToolArguments(t),o=Z(t),a=!0===t.isError;let i;if(r){if(i=se(r,s,n),!i){const e=z(r);return s&&(e.name=s),B(n)&&(e.arguments=n),e.progress=[...e.progress??[],{content:o,isError:a}],void(oe.tool+=1)}}else{const t=s?N(s):N();if(!t)return U(s),void e.logger.debug?.(`[im-sink] unattributed tool progress ignored requestId=${e.requestId} channel=${e.channelId} tool=${s??"unknown"} pending=${v.length}`);i=H(t,{name:s,arguments:n})}i&&(oe.tool+=1,i.observedResult||V(i,o,a),K(i),F(i.id),re(i,t))}),!0),sendBlockReply:e=>(le("block_reply",()=>{oe.block+=1,isNonEmptyString(e.text)&&(ae=!0!==e.isError?void 0:e.text)}),!0),sendFinalReply:t=>(le("final_reply",()=>{var r;(oe.final+=1,!0!==t.isError)?((t=>{const r=Y(t).filter(e=>!$.has(e));if(0===r.length)return;for(const e of r)$.add(e);const s=(async()=>{let t=[];try{t=await resolveToolArtifactLinks({toolCallId:`final:${e.runId??e.requestId}`,toolName:"final_reply_media",payloadMediaUrls:r})}catch(t){for(const e of r)$.delete(e);if(e.logger.warn?.(`[im-sink] final media enrichment failed requestId=${e.requestId} error=${t instanceof Error?t.message:String(t)}`),e.onCallbackFailure?.(t),e.onCallbackFailure)throw t;return}if(0!==t.length)await new Promise((r,s)=>{!1===e.callbackQueue.enqueueSync(()=>{try{if(e.abortSignal.aborted||e.stream.isTerminated)return;ee(t)}catch(t){e.logger.warn?.(`[im-sink] final media enrichment apply failed requestId=${e.requestId} error=${t instanceof Error?t.message:String(t)}`),e.onCallbackFailure?.(t),e.onCallbackFailure&&s(t)}finally{r()}})&&e.onCallbackFailure&&e.callbackQueue.waitForIdle().then(r,s)});else for(const e of r)$.delete(e)})();te(s)})(t),isNonEmptyString(t.text)&&(ae=void 0,l||(r=t.text,i="",a+=r,C(a),P(r),l=!0))):ae=t.text}),!0),waitForIdle:async()=>{for(let t=0;(e.onCallbackFailure||t<16)&&(await e.callbackQueue.waitForIdle(),0!==k.size);t++)e.onCallbackFailure?await Promise.all([...k]):await Promise.allSettled([...k]);await e.callbackQueue.waitForIdle();const t=takeFinalizeAttachments(e.sessionKey);t.length>0&&!e.abortSignal.aborted&&!e.stream.isTerminated&&ee(t)},getQueuedCounts:()=>({tool:oe.tool,block:oe.block,final:oe.final}),getAccumulatedBody:()=>o.text,getTerminalErrorText:()=>ae,markComplete:r=>{A(),(b.length>0||y.size>0)&&e.logger.debug?.(`[im-sink] dropping uncommitted lifecycle tool signals requestId=${e.requestId} legacy_hints=${b.length} buffered=${y.size}`),i="",C(a),m.receivedSnapshotCount>0&&logChatLatency(e.logger,"claw.text_preview.settled",e.requestId,t,{text_preview_snapshot_count:m.receivedSnapshotCount,text_preview_streaming_publish_count:m.streamingPublishCount,text_preview_terminal_publish_count:m.terminalPublishCount,text_preview_coalesced_snapshot_count:Math.max(0,m.receivedSnapshotCount-m.streamingPublishCount-m.terminalPublishCount),text_preview_publish_interval_ms:200});for(const t of f.values())try{"success"===r&&isUploadArtifactToolName(t.name)&&!t.durableUploadFilesEmitted&&re(t,{toolCallId:t.id,toolName:t.name}),"success"===r&&K(t),F(t.id)}catch(r){const s=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] tool finalization failed requestId=${e.requestId} toolUseId=${t.id} error=${s}`)}b.length=0,y.clear(),ie=!0}},replyOptions:{...e.runId?{runId:e.runId}:{},abortSignal:e.abortSignal,disableBlockStreaming:!0,onAgentRunStart:r=>{e.onAgentRunStart?.(r),logChatLatency(e.logger,"claw.runtime.run_started",e.requestId,t),e.logger.info?.(`[im-sink] run_start requestId=${e.requestId} runId=${r} channel=${e.channelId} in_reply_to=${e.inboundMessageId} origin=${e.origin??"im"}`)},onPartialReply:s=>{le("partial",()=>{"string"==typeof s.text&&(!r&&s.text.length>0&&(r=!0,logChatLatency(e.logger,"claw.model.first_delta",e.requestId,t)),i=s.text,(e=>{const t=c;if(!t){if(o.text===e)return;return q(e),void(c={targetBody:e,receivedSnapshotCount:1,streamingPublishCount:1,terminalPublishCount:0})}t.targetBody!==e&&(t.targetBody=e,t.receivedSnapshotCount+=1,w(t))})(a+i))})},onReasoningStream:t=>{le("reasoning",()=>{if(!isNonEmptyString(t.text))return;const r=t.text,s=p??(t=>{T();const r={partIndex:_,displaySeq:S,text:t,publishedText:t,receivedSnapshotCount:1,streamingPublishCount:1,startedAtMs:Date.now(),startedAtMonotonicMs:performance.now()};return e.stream.addPart(M(r,t,"streaming")),_+=1,S+=1,p=r,r})(r);r!==s.text&&(s.text.startsWith(r)||(s.text=r,s.receivedSnapshotCount+=1,O(s)))})},onReasoningEnd:()=>{le("reasoning_end",()=>{A()})},onAssistantMessageStart:()=>{le("assistant_message_start",()=>{i="",l=!1,C(a),e.logger.debug?.(`[im-sink] assistant_message_start requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`)})},onToolStart:r=>{le("tool_start",()=>{const n="string"==typeof r.phase?r.phase:"start",o=resolveRuntimeToolName(r)??"tool",a=resolveRuntimeToolCallId(r),i=resolveRuntimeToolArguments(r);if("update"===n)return void(a&&H(L(a),{name:o,arguments:i,pending:!0}));if(a&&s.set(a,Date.now()),logChatLatency(e.logger,"claw.tool.start",e.requestId,t,{tool:o}),a){H(a,{name:o,arguments:i,toolStartObserved:!0,pending:!0});const e=N(o);return void(e&&e!==a&&!h.has(a)&&(j(a,e),H(e,{name:o,arguments:i,toolStartObserved:!0,pending:!0})))}const l=(d=o,v.map(e=>f.get(e)).filter(e=>void 0!==e&&(!d||e.name===d)&&e.itemEventObserved));var d;if(1===l.length)return void H(l[0].id,{name:o,arguments:i,toolStartObserved:!0,pending:!0});if(l.length>1)return void e.logger.debug?.(`[im-sink] ambiguous id-less tool start ignored requestId=${e.requestId} channel=${e.channelId} tool=${o} candidates=${l.length}`);const u=[...y.entries()].filter(([,e])=>!e.name||e.name===o||"tool"===e.name);1!==u.length?b.push({name:o,arguments:i}):H(u[0][0],{name:o,arguments:i,toolStartObserved:!0,pending:!0})})},onItemEvent:e=>{le("item_event",()=>{const t="string"==typeof e.kind?e.kind.toLowerCase():"";if(t&&"tool"!==t)return;const r="string"==typeof e.phase?e.phase.toLowerCase():"update",s=resolveRuntimeToolCallId(e)??("string"==typeof e.itemId&&e.itemId.trim()?e.itemId.trim():void 0),n=resolveRuntimeToolName(e)??("string"==typeof e.title&&e.title.trim()?e.title.trim():void 0);s&&n&&("update"!==r?ne(s,n):H(L(s),{name:n,itemEventObserved:!0,pending:!0}))})}},commitAssistantMessage:e=>{le("assistant_message_commit",()=>{if(u.has(e.key))return;u.add(e.key),l=!0,ae=void 0,i="";const t=e.segments.filter(e=>"text"===e.type).map(e=>e.text).join("");a+=t,C(a);for(const t of e.segments)"text"!==t.type?J(t.id,t.name,t.arguments,!0):P(t.text)})},observeToolResult:r=>{le("tool_result_observation",()=>{const o=r.toolCallId.trim(),a=r.toolName.trim();if(!o||!a)return;const i=!n.has(o);if(i){n.add(o);const i=s.get(o);logChatLatency(e.logger,"claw.tool.result",e.requestId,t,{tool:a,tool_elapsed_ms:void 0===i?void 0:Math.max(0,Date.now()-i),outcome:r.isError?"error":"success",...r.isError?{error:summarizeObservedToolError(r.rawResult)??"error"}:{}})}if(e.persistObservedToolResults&&i){const e=observedToolResultText(r.rawResult);if(void 0!==e){const t=se(o,a);if(t)V(t,Z({text:e,isError:r.isError},t.artifactMediaUrls),r.isError),t.observedResult={content:e,isError:r.isError},K(t),F(t.id);else{const t=z(L(o));t.name??=a,t.observedResult={content:e,isError:r.isError}}}}const l=searchSourceProvider(r.rawResult)??"unknown";let d=0;try{const t=extractSearchSources({toolName:a,rawResult:r.rawResult,isError:r.isError});if(d=t.length,0===d)return;const s=se(o,a);if(s)R(t,s.id);else{const e=z(L(o));e.name??=a,e.sources=D(e.sources,t)}e.logger.debug?.(`[im-sink] search source projection requestId=${e.requestId} tool=${a} provider=${l} source_count=${d}`)}catch{e.logger.warn?.(`[im-sink] search source projection ignored requestId=${e.requestId} tool=${a} provider=${l} source_count=${d}`)}})},getSourceCount:()=>oe.source}}
@@ -1 +1 @@
1
- import{RUNTIME_ERROR_DESCRIPTORS,RUNTIME_HASH_DOMAINS,RUNTIME_INVOCATION_PARITY_ENTRIES,RUNTIME_INVOCATION_RECOVERY_CLASSES,SERVICE_CANONICAL_COMMAND_NAMES,mapCanonicalResultToService}from"@beeos-ai/beeos-types/runtime";import{reduceRuntimeRecoveryPolicy}from"@beeos-ai/beeos-types/runtime/internal";import{verifyAndCreateMessageServiceCoreExecutionAttempt}from"./core-execution-attempt-context.js";import{awaitRuntimeProjection,hasEffectReceiptHandoff,RuntimeCommandError}from"./runtime-command-dispatcher.js";import{createRuntimeAppendTimingRecorder}from"./runtime-append-timing.js";import{runtimeCommandIsReplayableQuery}from"./runtime-command-journal.js";import{RUNTIME_MESSAGE_TYPES,runtimeMessageBase,runtimeMessageHash,semanticEqual,validateRuntimeCancelEnvelope,validateRuntimeRequestEnvelope}from"./runtime-message-channel-contract.js";import{RuntimeResourceResolutionError}from"./runtime-operation-resource-resolver.js";import{RuntimeTransportFailurePolicy}from"@beeos-ai/cloud-agent-sdk";import{NativePromptExecutionFailure,nativePromptCancellationReason}from"./native-cloud-prompt-bridge.js";const leaseStarvationReportIntervalMs=3e4;export class MsRuntimeMessageChannelAdapter{dispatcher;channel;verifier;ports;journal;getLease;options;controller;running;externalDeliveryOwner;workers=new Map;poisonJournal;renewTransportFailurePolicy=new RuntimeTransportFailurePolicy;leaseStarvedSince;leaseStarvationReportedAt=0;receiptHistory=this;constructor(e,t,a,o,r,n,i){if(this.dispatcher=e,this.channel=t,this.verifier=a,this.ports=o,this.journal=r,this.getLease=n,this.options=i,!i.poisonJournal)throw new Error("durable poison journal is required");if(this.poisonJournal=i.poisonJournal,!Number.isSafeInteger(i.poisonDeliveryLimit??3)||(i.poisonDeliveryLimit??3)<=0)throw new Error("poison delivery limit must be a positive integer")}start(){if(this.externalDeliveryOwner)return void this.externalDeliveryOwner.start();if(this.running)return;const e=new AbortController;this.controller=e;const t=this.loop(e.signal).catch(t=>{e.signal.aborted||this.observeDeliveryError(t)}).finally(()=>{this.running===t&&(this.running=void 0)});this.running=t}async stop(e){this.controller?.abort();for(const e of this.workers.values())this.cancelWorker(e);if(this.externalDeliveryOwner)return await this.externalDeliveryOwner.stop(e),void await Promise.allSettled([...this.workers.values()].map(e=>e.completion));this.running&&await abortable(this.running,e)}attachExternalDeliveryOwner(e){if(this.running||this.externalDeliveryOwner)throw new Error("runtime delivery owner is already attached");this.externalDeliveryOwner=e}async acceptDelivery(e,t,a){if(this.currentLease(t),e.message.type===RUNTIME_MESSAGE_TYPES.cancel)return void await this.handleCancel(e,t);const o=validateRuntimeRequestEnvelope(e.message),r=o.ok?o.envelope.payload.operationId:e.message.channel_id;if(this.workers.has(r))return;const n={deliveryId:e.deliveryId,claimedLease:t,completion:Promise.resolve()};n.completion=this.handleRequest(e,t,a,e=>{this.setWorkerCancel(n,e)}).catch(e=>this.observeDeliveryError(e)).finally(()=>{this.workers.delete(r)}),this.workers.set(r,n),await n.completion}async acceptPoisonDelivery(e,t,a){await this.handlePoison(e,t,a)}async readOperationHistory(e){const t=this.getLease();if(!t)return{status:"unavailable"};try{return await this.channel.history({operationId:e.operationId,lease:t})}catch{return{status:"unavailable"}}}async loop(e){let t;(()=>{t||(t=setInterval(()=>{this.renewActive().catch(e=>this.observeDeliveryError(e))},this.options.renewIntervalMs??2e4),t.unref?.())})();try{for(;!e.aborted;){const t=this.getLease();if(!t){this.observeLeaseStarvation(),await delay(this.options.idleDelayMs??500,e);continue}let a;this.observeLeaseRestored();try{a=await this.channel.read({maxCount:this.options.readCount??32,blockMs:this.options.blockMs??5e3,lease:t,signal:e})}catch(t){if(e.aborted)return;this.observeDeliveryError(t),await delay(this.options.idleDelayMs??500,e);continue}for(const o of a){if(e.aborted)break;if(o.message.type===RUNTIME_MESSAGE_TYPES.cancel){await this.handleCancel(o,t).catch(e=>this.observeDeliveryError(e));continue}const a=o.message.channel_id;if(this.workers.has(a))continue;const r={deliveryId:o.deliveryId,claimedLease:t,completion:Promise.resolve()};r.completion=this.handleRequest(o,t,e,e=>{this.setWorkerCancel(r,e)}).catch(e=>this.observeDeliveryError(e)).finally(()=>{this.workers.delete(a)}),this.workers.set(a,r)}}}finally{t&&clearInterval(t),await Promise.allSettled([...this.workers.values()].map(e=>e.completion))}}observeDeliveryError(e){try{this.options.onDeliveryError?.(e)}catch{}}observeLeaseStarvation(){const e=Date.now();this.leaseStarvedSince??=e;const t=e-this.leaseStarvedSince;if(!(t<3e4||this.leaseStarvationReportedAt&&e-this.leaseStarvationReportedAt<3e4)){this.leaseStarvationReportedAt=e;try{this.options.onLeaseStarvation?.({starvedForMs:t,recovered:!1})}catch{}}}observeLeaseRestored(){const e=this.leaseStarvedSince;if(void 0===e)return;this.leaseStarvedSince=void 0;const t=this.leaseStarvationReportedAt;if(this.leaseStarvationReportedAt=0,t)try{this.options.onLeaseStarvation?.({starvedForMs:Date.now()-e,recovered:!0})}catch{}}observeRequestFailure(e,t,a){try{this.options.onRequestFailure?.({operationId:e,method:t,error:a})}catch{}}async renewActive(){const e=this.getLease();if(!e)return;const t=[];for(const a of this.workers.values())sameLeaseBinding(a.claimedLease,e)?t.push(a.deliveryId):this.cancelWorker(a);if(!t.length)return;let a;try{a=await this.channel.renew({deliveryIds:t,lease:e})}catch(e){if(this.observeDeliveryError(e),this.renewTransportFailurePolicy.recordFailure()){const e=new Set(t);for(const t of this.workers.values())e.has(t.deliveryId)&&this.cancelWorker(t)}return}if(this.renewTransportFailurePolicy.recordSuccess(),a.notPending.length){const e=new Set(a.notPending);for(const t of this.workers.values())e.has(t.deliveryId)&&this.cancelWorker(t)}}cancelWorker(e,t){e.cancelRequested||(e.cancelRequested=!0,e.cancelReason=t),e.cancel?.(e.cancelReason)}setWorkerCancel(e,t){const a=e.cancelRequested&&void 0===e.cancel;e.cancel=t,a&&t(e.cancelReason)}async handleCancel(e,t){const a=validateRuntimeCancelEnvelope(e.message);if(!a.ok)return void await this.handlePoison(e,`invalid_cancel:${a.reason}`,t);const o=a.envelope.payload,r=await this.channel.history({operationId:o.operationId,lease:t});if("found"===r.status&&r.snapshot.terminal&&"final_message"===r.snapshot.terminalSource)return void await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:t});if("not_found"===r.status||"expired"===r.status)return void await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:t});const n=r.snapshot.request.payload;if(n.operationId!==o.operationId||n.requestMessageId!==o.requestMessageId||n.requestHash!==o.requestHash||n.dispatchEpoch!==o.dispatchEpoch||n.method!==o.method)return void await this.handlePoison(e,"cancel_history_mismatch",t);await this.journal.observeCancellation({operationId:o.operationId,requestMessageId:o.requestMessageId,requestHash:o.requestHash,eventId:o.eventId});const i=n,s=2===i.schemaVersion&&"session/prompt"===i.method,d=this.workers.get(o.operationId);d&&this.cancelWorker(d,s?nativePromptCancellationReason:void 0),await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:t})}async handleRequest(e,t,a,o){const r=e.message.payload;if(2===r.schemaVersion&&"session/prompt"===r.method&&this.options.nativePromptBridge){let r;try{r=await this.options.nativePromptBridge.execute({delivery:e,lease:t,signal:a,setCancel:o})}catch(a){if(!(a instanceof NativePromptExecutionFailure))throw a;const o=await this.channel.append({operationId:a.request.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(a.request,a.failure,(new Date).toISOString())});return this.observeRequestTerminalAccepted(e.deliveryId,o.message),await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(t)}),void this.observeRequestAcknowledged(e.deliveryId,o.message)}if(r.replayedFinal)return this.observeRequestTerminalAccepted(e.deliveryId,r.replayedFinal),await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(t)}),void this.observeRequestAcknowledged(e.deliveryId,r.replayedFinal);if("succeeded"!==r.outcome){const a=await this.channel.append({operationId:r.request.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(r.request,new RuntimeCommandError("cancelled"===r.outcome?"OPERATION_CANCELLED":"EXECUTION_FAILED","native durable reply reports non-success"),(new Date).toISOString())});return this.observeRequestTerminalAccepted(e.deliveryId,a.message),await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(t)}),void this.observeRequestAcknowledged(e.deliveryId,a.message)}const n=runtimeMessageHash(RUNTIME_HASH_DOMAINS.coreResult,{method:r.request.method,result:r.result}),i={schemaVersion:1,operationId:r.request.operationId,method:r.request.method,coreResultRef:`sha256:${n}`,coreResultHash:n},s=runtimeMessageHash(RUNTIME_HASH_DOMAINS.effectRecord,i);await this.channel.append({operationId:r.request.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.effectCommitted,payload:{...runtimeMessageBase(r.request),effectRecord:i,effectRecordHash:s,committedAt:(new Date).toISOString()}});const d=await this.channel.append({operationId:r.request.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:{...runtimeMessageBase(r.request),outcome:r.outcome,response:{jsonrpc:"2.0",id:r.request.request.id,result:r.result},serviceResultHash:runtimeMessageHash(RUNTIME_HASH_DOMAINS.serviceResult,{method:r.request.method,result:r.result}),effectRecordHash:s,completedAt:(new Date).toISOString()}});return this.options.onRequestTerminalAccepted?.({deliveryId:e.deliveryId,message:d.message}),await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(t)}),void this.options.onRequestAcknowledged?.({deliveryId:e.deliveryId,message:d.message})}const n=validateRuntimeRequestEnvelope(e.message);if(!n.ok)return void await this.handlePoison(e,`invalid_request:${n.reason}`,t);if(n.envelope.payload.schemaVersion!==(this.options.requestSchemaVersion??1))return void await this.handlePoison(e,"request_realm_mismatch",t);const i=n.envelope.payload,s=e.executionGrant,d=createRuntimeAppendTimingRecorder("runtime-op",{operationId:i.operationId,method:i.method}),c=new AbortController;o(()=>c.abort());const l=async()=>{await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(t)}),d.mark("ack")},u=await this.channel.history({operationId:i.operationId,lease:t});if(d.mark("history"),"not_found"===u.status||"expired"===u.status)return void await l();if(u.snapshot.terminal&&"final_message"===u.snapshot.terminalSource)return void await l();if(this.options.allowedMethods&&!this.options.allowedMethods.has(i.method))return await this.reject(i,"unsupported_method",t),void await l();if("deadline"===u.snapshot.terminalSource||Date.parse(i.executionDeadlineAt)<=Date.now()||!u.snapshot.started&&Date.parse(i.claimDeadlineAt)<=Date.now())return await this.reject(i,"execution_deadline_exceeded",t),void await l();const p=await this.journal.getCancellation(i.operationId);d.mark("journal-cancel-read");const h=u.snapshot.cancelRequested||null!==p;if(h&&"queued"===u.snapshot.status)return await this.reject(i,"cancelled_before_dispatch",t),void await l();if(i.instanceId!==t.instanceId||i.runtimeHandlerIdentity!==t.handlerIdentity||i.dispatchEpoch!==t.runtimeEpoch)return await this.reject(i,"authority_mismatch",t),void await l();const m=u.snapshot.request.payload;if(u.snapshot.operationId!==i.operationId||u.snapshot.requestMessageId!==i.requestMessageId||u.snapshot.requestHash!==i.requestHash||!semanticEqual(m,i))return void await this.handlePoison(e,"request_history_mismatch",t);const I=u.snapshot.started?.payload,v=void 0!==I&&I.operationId===i.operationId&&I.requestMessageId===i.requestMessageId&&I.requestHash===i.requestHash&&I.executionGrantHash===i.executionGrantHash&&I.handlerIdentity===t.handlerIdentity&&I.dispatchEpoch===t.runtimeEpoch&&I.method===i.method,E=await this.journal.get(i.operationId);d.mark("journal-prior");const f=runtimeCommandIsReplayableQuery(i.command.name),R=f?ephemeralQueryAccept(i):await this.journal.acceptMessageRequest({operationId:i.operationId,command:i.command.name,paramsHash:i.paramsHash,runtimeEpoch:i.dispatchEpoch,requestMessageId:i.requestMessageId,requestHash:i.requestHash});d.mark("journal-accept");const y=v?E:R,w=f?"execute":decideMessageServiceRecovery(u.snapshot,i,y,v);if("already_terminal"===w)return void await l();if(!CORE_RECOVERY_DECISIONS.has(w))return f||await this.markOutcomeUnknownIfMutable(R),await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(i,new RuntimeCommandError("OUTCOME_UNKNOWN",`Types recovery policy requires ${w}; this runtime cannot safely replay Core`),(new Date).toISOString())}),void await l();if(await this.verifier.refresh(),d.mark("verifier-refresh"),!s)return v?await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(i,new RuntimeCommandError("OUTCOME_UNKNOWN","retained started proof has no live execution grant"),(new Date).toISOString())}):await this.reject(i,"invalid_execution_grant",t),void await l();this.verifier.verifyAndDecodeGrant(s)||await this.verifier.refresh(!0);const _=()=>c.abort();let g;a.addEventListener("abort",_,{once:!0});try{g=await verifyAndCreateMessageServiceCoreExecutionAttempt({request:i,executionGrant:s,runtimeEpoch:t.runtimeEpoch,lease:t,verifier:this.verifier,allowExpiredGrant:v,abortSignal:c.signal,resolvePorts:async()=>await this.ports.resolve({request:i,executionGrant:s,command:i.command,getLease:()=>this.currentLease(t),...this.journalLineage(),journalRecord:R,abortSignal:c.signal})})}catch(e){if(a.removeEventListener("abort",_),c.abort(),!(e instanceof RuntimeResourceResolutionError))throw e;if("transient"===e.kind)return;return v?(f||await this.markOutcomeUnknownIfMutable(R),await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(i,new RuntimeCommandError("OUTCOME_UNKNOWN","eager resources cannot be reconstructed after retained started proof"),(new Date).toISOString())})):await this.reject(i,"integrity_mismatch"===e.kind?"resource_integrity_mismatch":"resource_resolution_rejected",t),void await l()}if(!g.ok)return a.removeEventListener("abort",_),c.abort(),v?(f||await this.markOutcomeUnknownIfMutable(R),await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(i,new RuntimeCommandError("OUTCOME_UNKNOWN","execution grant cannot be revalidated after retained started proof"),(new Date).toISOString())})):await this.reject(i,"invalid_execution_grant",t),void await l();if(!h||"prepared"!==R.phase&&"started"!==R.phase||c.abort(),c.signal.aborted&&!v)return a.removeEventListener("abort",_),await this.reject(i,"cancelled_before_dispatch",t),void await l();d.mark("attempt"),v?this.currentLease(t):(await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),executionGrant:s,type:RUNTIME_MESSAGE_TYPES.started,payload:{...runtimeMessageBase(i),executionMode:"start",executionGrantHash:i.executionGrantHash,handlerIdentity:t.handlerIdentity,claimedAt:R.messageBinding?.acceptedAt??R.updatedAt}}),d.mark("append-started"));const S=this.dispatcher.dispatch(i.command,g.context);S.completion.catch(()=>{}),o(()=>{c.abort(),S.cancel()}),c.signal.aborted&&S.cancel();const M=this.forwardProgress(i,S.progress,t).catch(()=>{});let N,O=!1;try{if(("mcp/set"===i.method||"mcp/unset"===i.method)&&hasEffectReceiptHandoff(S)){const e=await S.effectCommitted;if(e){if(e.operationId!==i.operationId||e.method!==i.command.name)throw new RuntimeCommandError("OUTCOME_UNKNOWN","Core MCP receipt correlation mismatch");const a=runtimeMessageHash(RUNTIME_HASH_DOMAINS.coreResult,{method:i.method,result:e.result}),o={schemaVersion:1,operationId:i.operationId,method:i.method,coreResultRef:`sha256:${a}`,coreResultHash:a};N=runtimeMessageHash(RUNTIME_HASH_DOMAINS.effectRecord,o),O=!0,await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.effectCommitted,payload:{...runtimeMessageBase(i),effectRecord:o,effectRecordHash:N,committedAt:e.committedAt}}),await S.acknowledgeEffectReceipt({operationId:i.operationId,method:i.command.name,effectRecordHash:N})}}const a=await S.completion;if(await M,d.mark("core"),f){const o=(new Date).toISOString();let r;try{r=sanitizeRuntimeServiceResult(i.method,a,g.context,void 0)}catch(e){throw new RuntimeCommandError("OUTCOME_UNKNOWN","committed Core result cannot be mapped safely",void 0,{cause:e})}const n=runtimeMessageHash(RUNTIME_HASH_DOMAINS.serviceResult,{method:i.method,result:r}),s=await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:{...runtimeMessageBase(i),outcome:"succeeded",response:{jsonrpc:"2.0",id:i.request.id,result:r},serviceResultHash:n,completedAt:o}});return d.mark("append-final"),this.observeRequestTerminalAccepted(e.deliveryId,s.message),await l(),void this.observeRequestAcknowledged(e.deliveryId,s.message)}const o=await this.journal.get(i.operationId);if(d.mark("journal-after-core"),!o||!isCommittedCorePhase(o.phase))throw new RuntimeCommandError("OUTCOME_UNKNOWN","Core completed without a committed local journal record");const r=o.updatedAt;let n,s;if("query"!==RUNTIME_INVOCATION_RECOVERY_CLASSES[i.method]){const e=isAgentProjectionMethod(i.method),s=S.getSnapshot().projection,c=o.agentProjectionIntent??o.agentProjectionPreparationFailure;if(e&&!c)throw new RuntimeCommandError("OUTCOME_UNKNOWN","agent effect committed without an atomic projection preparation record");if(!N&&"session/clear"!==i.method){const e=c?.coreResultHash??runtimeMessageHash(RUNTIME_HASH_DOMAINS.coreResult,{method:i.method,result:a}),n=o.agentProjectionIntent?.projectionRevision??(methodRequiresProjectionRevision(i.method)?s?.revision??`${Math.max(0,o.revision)}`:void 0),l={schemaVersion:1,operationId:i.operationId,method:i.method,coreResultRef:`sha256:${e}`,coreResultHash:e,...n?{projectionRevision:n}:{}};N=runtimeMessageHash(RUNTIME_HASH_DOMAINS.effectRecord,l),O=!0,await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.effectCommitted,payload:{...runtimeMessageBase(i),effectRecord:l,effectRecordHash:N,committedAt:r}}),d.mark("append-effect")}let u=e?await awaitRuntimeProjection(S):s;if("session/set_model"===i.method&&"synced"!==u?.state&&(u=await this.projectSessionModelAfterEffect(i,g.context,o,u),d.mark("set-model-projection")),e&&o.agentProjectionIntent&&(!u||u.revision!==o.agentProjectionIntent.projectionRevision))throw new RuntimeCommandError("OUTCOME_UNKNOWN","agent projection receipt revision mismatch");if("pending"===u?.state)return void await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.projectionPending,payload:{...runtimeMessageBase(i),revision:u.revision}});if("synced"===u?.state&&await this.publishProjectionSynced(i,t,{...u,state:"synced"}),"blocked"===u?.state){await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.projectionBlocked,payload:{...runtimeMessageBase(i),revision:u.revision,errorCode:"PROJECTION_BLOCKED"}});const e=RUNTIME_ERROR_DESCRIPTORS.PROJECTION_BLOCKED;return await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:{...runtimeMessageBase(i),outcome:"projection_blocked",response:{jsonrpc:"2.0",id:i.request.id,error:{code:e.jsonRpcCode,message:"PROJECTION_BLOCKED",data:{code:"PROJECTION_BLOCKED",operationId:i.operationId,effectState:"committed",retryMode:e.retryMode}}},effectRecordHash:N,completedAt:r}}),void await l()}n=e?u?.platformAgentId:void 0}try{s=sanitizeRuntimeServiceResult(i.method,a,g.context,n)}catch(e){throw new RuntimeCommandError("OUTCOME_UNKNOWN","committed Core result cannot be mapped safely",void 0,{cause:e})}const c=runtimeMessageHash(RUNTIME_HASH_DOMAINS.serviceResult,{method:i.method,result:s});O=!0;const u=await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:{...runtimeMessageBase(i),outcome:"succeeded",response:{jsonrpc:"2.0",id:i.request.id,result:s},serviceResultHash:c,...N?{effectRecordHash:N}:{},completedAt:r}});if(d.mark("append-final"),this.observeRequestTerminalAccepted(e.deliveryId,u.message),("mcp/set"===i.method||"mcp/unset"===i.method)&&hasEffectReceiptHandoff(S)&&"function"==typeof S.acknowledgeTerminalReceipt){if(!N)throw new RuntimeCommandError("OUTCOME_UNKNOWN","MCP terminal response lacks its committed effect hash");await S.acknowledgeTerminalReceipt({operationId:i.operationId,method:i.command.name,effectRecordHash:N,terminalMessageId:u.message.message_id})}await l(),this.observeRequestAcknowledged(e.deliveryId,u.message)}catch(e){const a=await this.journal.get(i.operationId);if(a&&isCommittedCorePhase(a.phase)&&O)throw e;const o=!a||!isCommittedCorePhase(a.phase)||e instanceof RuntimeCommandError&&"OUTCOME_UNKNOWN"===e.code?e:new RuntimeCommandError("OUTCOME_UNKNOWN","Core effect committed before terminal mapping",void 0,{cause:e});this.observeRequestFailure(i.operationId,i.method,o);const r=failurePayload(i,o,a?.updatedAt??(new Date).toISOString());await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:r}),d.mark("append-terminal-failure"),await l()}finally{d.finish(),c.abort(),a.removeEventListener("abort",_)}}async handlePoison(e,t,a){this.currentLease(a);(await this.poisonJournal.record({delivery:e,reason:durablePoisonReason(t),limit:this.options.poisonDeliveryLimit??3})).terminal&&await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(a)})}observeRequestTerminalAccepted(e,t){try{this.options.onRequestTerminalAccepted?.({deliveryId:e,message:t})}catch{}}observeRequestAcknowledged(e,t){try{this.options.onRequestAcknowledged?.({deliveryId:e,message:t})}catch{}}async forwardProgress(e,t,a){for await(const o of t)await this.channel.append({operationId:e.operationId,lease:this.currentLease(a),type:RUNTIME_MESSAGE_TYPES.progress,payload:{...runtimeMessageBase(e),phase:o.phase,progress:o}})}async reject(e,t,a){await this.channel.append({operationId:e.operationId,lease:this.currentLease(a),type:RUNTIME_MESSAGE_TYPES.final,payload:prestartFailurePayload(e,t)})}async markOutcomeUnknownIfMutable(e){"prepared"!==e.phase&&"started"!==e.phase||await this.journal.transition({operationId:e.operationId,expectedRevision:e.revision,phase:"outcome_unknown",errorCode:"OUTCOME_UNKNOWN"})}async projectSessionModelAfterEffect(e,t,a,o){const r=Object.freeze({state:"pending",revision:o?.revision??`${Math.max(0,a.revision)}`}),n=e.command;if("session.setModel"!==n.name||"conversation"!==n.context.scope)return r;const i=t.sessionModelProjection;if(!i)return r;try{await i.project({conversationId:n.context.conversation.runtimeConversationUid,modelOverrideId:n.params.modelOverrideId});const e=Object.freeze({state:"synced",revision:r.revision});try{const t=await this.journal.get(a.operationId)??a;if("projection_committed"===t.phase&&"synced"===t.projectionReceipt?.snapshot.state)return Object.freeze({state:"synced",revision:t.projectionReceipt.snapshot.revision});await this.journal.transition({operationId:t.operationId,expectedRevision:t.revision,phase:"projection_committed",projectionSnapshot:e})}catch{}return e}catch(e){return this.observeDeliveryError(e),r}}async publishProjectionSynced(e,t,a){const o=this.currentLease(t),r=await this.channel.history({operationId:e.operationId,lease:o});if("found"===r.status&&"synced"===r.snapshot.projectionState)return;const n={...runtimeMessageBase(e),revision:a.revision};("found"!==r.status||"reserved"===r.snapshot.projectionState||"pending"!==r.snapshot.projectionState&&void 0===r.snapshot.projectionPending)&&await this.channel.append({operationId:e.operationId,lease:o,type:RUNTIME_MESSAGE_TYPES.projectionPending,payload:n}),await this.channel.append({operationId:e.operationId,lease:o,type:RUNTIME_MESSAGE_TYPES.projectionSynced,payload:{...n,...a.platformAgentId?{platformAgentId:a.platformAgentId}:{}}})}journalLineage(){return this.options.getJournalLineage?.()??{journalStoreId:this.options.journalStoreId,journalGeneration:this.options.journalGeneration}}currentLease(e){const t=this.getLease();if(!t||t.instanceId!==e.instanceId||t.leaseId!==e.leaseId||t.runtimeEpoch!==e.runtimeEpoch||t.handlerIdentity!==e.handlerIdentity||!Number.isFinite(Date.parse(t.leaseExpiresAt))||Date.parse(t.leaseExpiresAt)<=Date.now())throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","runtime message lease changed");return t}}function ephemeralQueryAccept(e){return{operationId:e.operationId,command:e.command.name,paramsHash:e.paramsHash,runtimeEpoch:e.dispatchEpoch,phase:"prepared",revision:1,updatedAt:(new Date).toISOString(),messageBinding:{requestMessageId:e.requestMessageId,requestHash:e.requestHash,acceptedAt:(new Date).toISOString()}}}function durablePoisonReason(e){const t=e.replace(/[^a-z0-9_:.-]+/gi,"_").replace(/^_+|_+$/g,"").slice(0,256);if(!t)throw new Error("poison reason is empty");return t}function isCommittedCorePhase(e){return"effect_committed"===e||"projection_committed"===e}const CORE_RECOVERY_DECISIONS=new Set(["execute","resume","replay_effect_committed","resume_projection","publish_committed_result","publish_projected_result","publish_terminal_result"]);function decideMessageServiceRecovery(e,t,a,o){const r=RUNTIME_INVOCATION_PARITY_ENTRIES.find(e=>e.acpMethod===t.method),n=e.terminal?"terminal":"blocked"===e.projectionState?"projection_blocked":"synced"===e.projectionState?"projection_synced":"pending"===e.projectionState?"projection_pending":e.effectCommitted?"runtime_committed":o?"running":"queued",i="failed"===a?.phase||"outcome_unknown"===a?.phase?"terminal":a?.phase,s=a&&a.runtimeEpoch===t.dispatchEpoch&&(void 0===a.messageBinding||a.messageBinding.requestMessageId===t.requestMessageId&&a.messageBinding.requestHash===t.requestHash)?"continuous":"discontinuous";return reduceRuntimeRecoveryPolicy({recoveryClass:r?.recoveryClass??RUNTIME_INVOCATION_RECOVERY_CLASSES[t.method],projectionRequired:"mcp/set"===t.method||"mcp/unset"===t.method||(r?.projectionRequired??!1),messageServicePhase:n,executionBoundaryCrossed:o,lineageContinuity:s,journalState:a?"available":"unavailable",...i?{journalPhase:i}:{}})}export function sanitizeRuntimeServiceResult(e,t,a,o){if("session/clear"===e)return serviceClearResult(t,a?.historyBoundary);if("session/set_model"===e)return serviceSetModelResult(t,a);if(!(e in SERVICE_CANONICAL_COMMAND_NAMES))return t;const r="cron/status"===e&&record(t)?{enabled:t.enabled,jobCount:t.jobCount,..."number"==typeof t.nextWakeAtMs?{nextWakeAtMs:t.nextWakeAtMs}:{}}:t;return mapCanonicalResultToService(e,r,{...o?{platformAgentId:o}:{},classifySkillOrigin:e=>e.bundled?{origin:"bundled",slug:e.slug}:{origin:"legacy_runtime",slug:e.slug},resolveMcpView:e=>({name:e.name,transport:e.transport,origin:"legacy_runtime",...void 0===e.connected?{}:{connected:e.connected},...void 0===e.connectionTimeoutMs?{}:{connectionTimeoutMs:e.connectionTimeoutMs}}),sanitizeDiagnostic:e=>/^[A-Z][A-Z0-9_]{0,63}$/.test(e)?e:"RUNTIME_EXECUTION_FAILED"})}function serviceClearResult(e,t){if(!record(e)||!0!==e.cleared||"string"!=typeof e.historyGeneration||!t||"message-service"!==t.kind)throw new RuntimeCommandError("OUTCOME_UNKNOWN","committed clear result lacks its Message Service receipt");const a=t;if(!a.committedIntentId)throw new RuntimeCommandError("OUTCOME_UNKNOWN","Message Service clear receipt is unavailable");return{...e,clearIntentId:a.committedIntentId()}}function serviceSetModelResult(e,t){if(!record(e)||"string"!=typeof e.effectiveModelId||!t)throw new RuntimeCommandError("OUTCOME_UNKNOWN","committed set_model result is invalid");const a=t.verifiedMessageGrant?.claims.command;if(!a||"session.setModel"!==a.name||"conversation"!==a.context.scope)throw new RuntimeCommandError("OUTCOME_UNKNOWN","set_model Service target receipt is unavailable");const o=a.params.modelOverrideId;return{conversationId:a.context.conversation.runtimeConversationUid,...null===o?{defaultModelId:e.effectiveModelId}:{},modelOverrideId:o,effectiveModelId:e.effectiveModelId,effectState:"committed",projectionState:"synced",operationId:t.operationId}}function isAgentProjectionMethod(e){return"agent/create"===e||"agent/update"===e||"agent/delete"===e||"agent/applyTemplate"===e}function methodRequiresProjectionRevision(e){return isAgentProjectionMethod(e)||"session/set_model"===e}function record(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}function sameLeaseBinding(e,t){return e.instanceId===t.instanceId&&e.leaseId===t.leaseId&&e.handlerIdentity===t.handlerIdentity&&e.runtimeEpoch===t.runtimeEpoch}function failurePayload(e,t,a){const o=t instanceof RuntimeCommandError?t.code:"RUNTIME_EXECUTION_FAILED",r=o in RUNTIME_ERROR_DESCRIPTORS?o:"RUNTIME_EXECUTION_FAILED",n="OUTCOME_UNKNOWN"===r||"INSTANCE_EPOCH_MISMATCH"===r?"outcome_unknown":"COMMAND_EXPIRED"===r?"expired":"OPERATION_CANCELLED"===r?"cancelled":"failed",i="outcome_unknown"===n?"OUTCOME_UNKNOWN":r,s=RUNTIME_ERROR_DESCRIPTORS[i],d="outcome_unknown"===n?"outcome_unknown":n;return{...runtimeMessageBase(e),outcome:n,response:{jsonrpc:"2.0",id:e.request.id,error:{code:s.jsonRpcCode,message:i,data:{code:i,operationId:e.operationId,effectState:d,retryMode:s.retryMode}}},completedAt:a}}function prestartFailurePayload(e,t){const a="invalid_execution_grant"===t?"INVALID_EXECUTION_GRANT":"unsupported_method"===t?"METHOD_NOT_SUPPORTED":"authority_mismatch"===t?"INSTANCE_EPOCH_MISMATCH":"execution_deadline_exceeded"===t?"COMMAND_EXPIRED":"cancelled_before_dispatch"===t?"OPERATION_CANCELLED":"resource_resolution_rejected"===t?"INVALID_INVOCATION":"RUNTIME_EXECUTION_FAILED",o=RUNTIME_ERROR_DESCRIPTORS[a in RUNTIME_ERROR_DESCRIPTORS?a:"RUNTIME_EXECUTION_FAILED"],r="COMMAND_EXPIRED"===a?"expired":"OPERATION_CANCELLED"===a?"cancelled":"failed";return{...runtimeMessageBase(e),outcome:r,response:{jsonrpc:"2.0",id:e.request.id,error:{code:o.jsonRpcCode,message:a,data:{code:a,operationId:e.operationId,effectState:r,retryMode:o.retryMode}}},completedAt:(new Date).toISOString()}}function abortable(e,t){return t?t.aborted?Promise.resolve():new Promise((a,o)=>{const r=()=>a();t.addEventListener("abort",r,{once:!0}),e.then(()=>{t.removeEventListener("abort",r),a()},e=>{t.removeEventListener("abort",r),o(e)})}):e}function delay(e,t){return new Promise(a=>{if(t?.aborted)return a();const o=()=>{clearTimeout(r),a()},r=setTimeout(()=>{t?.removeEventListener("abort",o),a()},e);t?.addEventListener("abort",o,{once:!0})})}
1
+ import{RUNTIME_ERROR_DESCRIPTORS,RUNTIME_HASH_DOMAINS,RUNTIME_INVOCATION_PARITY_ENTRIES,RUNTIME_INVOCATION_RECOVERY_CLASSES,SERVICE_CANONICAL_COMMAND_NAMES,mapCanonicalResultToService}from"@beeos-ai/beeos-types/runtime";import{reduceRuntimeRecoveryPolicy}from"@beeos-ai/beeos-types/runtime/internal";import{verifyAndCreateMessageServiceCoreExecutionAttempt}from"./core-execution-attempt-context.js";import{awaitRuntimeProjection,hasEffectReceiptHandoff,RuntimeCommandError}from"./runtime-command-dispatcher.js";import{createRuntimeAppendTimingRecorder}from"./runtime-append-timing.js";import{runtimeCommandIsReplayableQuery}from"./runtime-command-journal.js";import{RUNTIME_MESSAGE_TYPES,runtimeMessageBase,runtimeMessageHash,semanticEqual,validateRuntimeCancelEnvelope,validateRuntimeRequestEnvelope}from"./runtime-message-channel-contract.js";import{RuntimeResourceResolutionError}from"./runtime-operation-resource-resolver.js";import{RuntimeTransportFailurePolicy}from"@beeos-ai/cloud-agent-sdk";import{NativePromptExecutionFailure,nativePromptCancellationReason}from"./native-cloud-prompt-bridge.js";const leaseStarvationReportIntervalMs=3e4;export class MsRuntimeMessageChannelAdapter{dispatcher;channel;verifier;ports;journal;getLease;options;controller;running;externalDeliveryOwner;workers=new Map;poisonJournal;renewTransportFailurePolicy=new RuntimeTransportFailurePolicy;leaseStarvedSince;leaseStarvationReportedAt=0;receiptHistory=this;constructor(e,t,a,o,r,n,i){if(this.dispatcher=e,this.channel=t,this.verifier=a,this.ports=o,this.journal=r,this.getLease=n,this.options=i,!i.poisonJournal)throw new Error("durable poison journal is required");if(this.poisonJournal=i.poisonJournal,!Number.isSafeInteger(i.poisonDeliveryLimit??3)||(i.poisonDeliveryLimit??3)<=0)throw new Error("poison delivery limit must be a positive integer")}start(){if(this.externalDeliveryOwner)return void this.externalDeliveryOwner.start();if(this.running)return;const e=new AbortController;this.controller=e;const t=this.loop(e.signal).catch(t=>{e.signal.aborted||this.observeDeliveryError(t)}).finally(()=>{this.running===t&&(this.running=void 0)});this.running=t}async stop(e){this.controller?.abort();for(const e of this.workers.values())this.cancelWorker(e);if(this.externalDeliveryOwner)return await this.externalDeliveryOwner.stop(e),void await Promise.allSettled([...this.workers.values()].map(e=>e.completion));this.running&&await abortable(this.running,e)}attachExternalDeliveryOwner(e){if(this.running||this.externalDeliveryOwner)throw new Error("runtime delivery owner is already attached");this.externalDeliveryOwner=e}async acceptDelivery(e,t,a){if(this.currentLease(t),e.message.type===RUNTIME_MESSAGE_TYPES.cancel)return void await this.handleCancel(e,t);const o=validateRuntimeRequestEnvelope(e.message),r=o.ok?o.envelope.payload.operationId:e.message.channel_id;if(this.workers.has(r))return;const n={deliveryId:e.deliveryId,claimedLease:t,completion:Promise.resolve()};n.completion=this.handleRequest(e,t,a,e=>{this.setWorkerCancel(n,e)}).catch(e=>this.observeDeliveryError(e)).finally(()=>{this.workers.delete(r)}),this.workers.set(r,n),await n.completion}async acceptPoisonDelivery(e,t,a){await this.handlePoison(e,t,a)}async readOperationHistory(e){const t=this.getLease();if(!t)return{status:"unavailable"};try{return await this.channel.history({operationId:e.operationId,lease:t})}catch{return{status:"unavailable"}}}async loop(e){let t;(()=>{t||(t=setInterval(()=>{this.renewActive().catch(e=>this.observeDeliveryError(e))},this.options.renewIntervalMs??2e4),t.unref?.())})();try{for(;!e.aborted;){const t=this.getLease();if(!t){this.observeLeaseStarvation(),await delay(this.options.idleDelayMs??500,e);continue}let a;this.observeLeaseRestored();try{a=await this.channel.read({maxCount:this.options.readCount??32,blockMs:this.options.blockMs??5e3,lease:t,signal:e})}catch(t){if(e.aborted)return;this.observeDeliveryError(t),await delay(this.options.idleDelayMs??500,e);continue}for(const o of a){if(e.aborted)break;if(o.message.type===RUNTIME_MESSAGE_TYPES.cancel){await this.handleCancel(o,t).catch(e=>this.observeDeliveryError(e));continue}const a=o.message.channel_id;if(this.workers.has(a))continue;const r={deliveryId:o.deliveryId,claimedLease:t,completion:Promise.resolve()};r.completion=this.handleRequest(o,t,e,e=>{this.setWorkerCancel(r,e)}).catch(e=>this.observeDeliveryError(e)).finally(()=>{this.workers.delete(a)}),this.workers.set(a,r)}}}finally{t&&clearInterval(t),await Promise.allSettled([...this.workers.values()].map(e=>e.completion))}}observeDeliveryError(e){try{this.options.onDeliveryError?.(e)}catch{}}observeLeaseStarvation(){const e=Date.now();this.leaseStarvedSince??=e;const t=e-this.leaseStarvedSince;if(!(t<3e4||this.leaseStarvationReportedAt&&e-this.leaseStarvationReportedAt<3e4)){this.leaseStarvationReportedAt=e;try{this.options.onLeaseStarvation?.({starvedForMs:t,recovered:!1})}catch{}}}observeLeaseRestored(){const e=this.leaseStarvedSince;if(void 0===e)return;this.leaseStarvedSince=void 0;const t=this.leaseStarvationReportedAt;if(this.leaseStarvationReportedAt=0,t)try{this.options.onLeaseStarvation?.({starvedForMs:Date.now()-e,recovered:!0})}catch{}}observeRequestFailure(e,t,a){try{this.options.onRequestFailure?.({operationId:e,method:t,error:a})}catch{}}async renewActive(){const e=this.getLease();if(!e)return;const t=[];for(const a of this.workers.values())sameLeaseBinding(a.claimedLease,e)?t.push(a.deliveryId):this.cancelWorker(a);if(!t.length)return;let a;try{a=await this.channel.renew({deliveryIds:t,lease:e})}catch(e){if(this.observeDeliveryError(e),this.renewTransportFailurePolicy.recordFailure()){const e=new Set(t);for(const t of this.workers.values())e.has(t.deliveryId)&&this.cancelWorker(t)}return}if(this.renewTransportFailurePolicy.recordSuccess(),a.notPending.length){const e=new Set(a.notPending);for(const t of this.workers.values())e.has(t.deliveryId)&&this.cancelWorker(t)}}cancelWorker(e,t){e.cancelRequested||(e.cancelRequested=!0,e.cancelReason=t),e.cancel?.(e.cancelReason)}setWorkerCancel(e,t){const a=e.cancelRequested&&void 0===e.cancel;e.cancel=t,a&&t(e.cancelReason)}async handleCancel(e,t){const a=validateRuntimeCancelEnvelope(e.message);if(!a.ok)return void await this.handlePoison(e,`invalid_cancel:${a.reason}`,t);const o=a.envelope.payload,r=await this.channel.history({operationId:o.operationId,lease:t});if("found"===r.status&&r.snapshot.terminal&&"final_message"===r.snapshot.terminalSource)return void await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:t});if("not_found"===r.status||"expired"===r.status)return void await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:t});const n=r.snapshot.request.payload;if(n.operationId!==o.operationId||n.requestMessageId!==o.requestMessageId||n.requestHash!==o.requestHash||n.dispatchEpoch!==o.dispatchEpoch||n.method!==o.method)return void await this.handlePoison(e,"cancel_history_mismatch",t);await this.journal.observeCancellation({operationId:o.operationId,requestMessageId:o.requestMessageId,requestHash:o.requestHash,eventId:o.eventId});const i=n,s=2===i.schemaVersion&&"session/prompt"===i.method,d=this.workers.get(o.operationId);d&&this.cancelWorker(d,s?nativePromptCancellationReason:void 0),await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:t})}async handleRequest(e,t,a,o){const r=e.message.payload;if(2===r.schemaVersion&&"session/prompt"===r.method&&this.options.nativePromptBridge){let r;try{r=await this.options.nativePromptBridge.execute({delivery:e,lease:t,signal:a,setCancel:o})}catch(a){if(!(a instanceof NativePromptExecutionFailure))throw a;a.failure instanceof RuntimeCommandError&&Object.prototype.hasOwnProperty.call(RUNTIME_ERROR_DESCRIPTORS,a.failure.code)&&a.failure.code;const o=await this.channel.append({operationId:a.request.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(a.request,a.failure,(new Date).toISOString())});return this.observeRequestTerminalAccepted(e.deliveryId,o.message),await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(t)}),void this.observeRequestAcknowledged(e.deliveryId,o.message)}if(r.replayedFinal)return this.observeRequestTerminalAccepted(e.deliveryId,r.replayedFinal),await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(t)}),void this.observeRequestAcknowledged(e.deliveryId,r.replayedFinal);if("succeeded"!==r.outcome){const a=await this.channel.append({operationId:r.request.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(r.request,new RuntimeCommandError("cancelled"===r.outcome?"OPERATION_CANCELLED":"EXECUTION_FAILED","native durable reply reports non-success"),(new Date).toISOString())});return this.observeRequestTerminalAccepted(e.deliveryId,a.message),await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(t)}),void this.observeRequestAcknowledged(e.deliveryId,a.message)}const n=runtimeMessageHash(RUNTIME_HASH_DOMAINS.coreResult,{method:r.request.method,result:r.result}),i={schemaVersion:1,operationId:r.request.operationId,method:r.request.method,coreResultRef:`sha256:${n}`,coreResultHash:n},s=runtimeMessageHash(RUNTIME_HASH_DOMAINS.effectRecord,i);await this.channel.append({operationId:r.request.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.effectCommitted,payload:{...runtimeMessageBase(r.request),effectRecord:i,effectRecordHash:s,committedAt:(new Date).toISOString()}});const d=await this.channel.append({operationId:r.request.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:{...runtimeMessageBase(r.request),outcome:r.outcome,response:{jsonrpc:"2.0",id:r.request.request.id,result:r.result},serviceResultHash:runtimeMessageHash(RUNTIME_HASH_DOMAINS.serviceResult,{method:r.request.method,result:r.result}),effectRecordHash:s,completedAt:(new Date).toISOString()}});return this.options.onRequestTerminalAccepted?.({deliveryId:e.deliveryId,message:d.message}),await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(t)}),void this.options.onRequestAcknowledged?.({deliveryId:e.deliveryId,message:d.message})}const n=validateRuntimeRequestEnvelope(e.message);if(!n.ok)return void await this.handlePoison(e,`invalid_request:${n.reason}`,t);if(n.envelope.payload.schemaVersion!==(this.options.requestSchemaVersion??1))return void await this.handlePoison(e,"request_realm_mismatch",t);const i=n.envelope.payload,s=e.executionGrant,d=createRuntimeAppendTimingRecorder("runtime-op",{operationId:i.operationId,method:i.method}),c=new AbortController;o(()=>c.abort());const l=async()=>{await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(t)}),d.mark("ack")},u=await this.channel.history({operationId:i.operationId,lease:t});if(d.mark("history"),"not_found"===u.status||"expired"===u.status)return void await l();if(u.snapshot.terminal&&"final_message"===u.snapshot.terminalSource)return void await l();if(this.options.allowedMethods&&!this.options.allowedMethods.has(i.method))return await this.reject(i,"unsupported_method",t),void await l();if("deadline"===u.snapshot.terminalSource||Date.parse(i.executionDeadlineAt)<=Date.now()||!u.snapshot.started&&Date.parse(i.claimDeadlineAt)<=Date.now())return await this.reject(i,"execution_deadline_exceeded",t),void await l();const p=await this.journal.getCancellation(i.operationId);d.mark("journal-cancel-read");const h=u.snapshot.cancelRequested||null!==p;if(h&&"queued"===u.snapshot.status)return await this.reject(i,"cancelled_before_dispatch",t),void await l();if(i.instanceId!==t.instanceId||i.runtimeHandlerIdentity!==t.handlerIdentity||i.dispatchEpoch!==t.runtimeEpoch)return await this.reject(i,"authority_mismatch",t),void await l();const m=u.snapshot.request.payload;if(u.snapshot.operationId!==i.operationId||u.snapshot.requestMessageId!==i.requestMessageId||u.snapshot.requestHash!==i.requestHash||!semanticEqual(m,i))return void await this.handlePoison(e,"request_history_mismatch",t);const I=u.snapshot.started?.payload,E=void 0!==I&&I.operationId===i.operationId&&I.requestMessageId===i.requestMessageId&&I.requestHash===i.requestHash&&I.executionGrantHash===i.executionGrantHash&&I.handlerIdentity===t.handlerIdentity&&I.dispatchEpoch===t.runtimeEpoch&&I.method===i.method,v=await this.journal.get(i.operationId);d.mark("journal-prior");const f=runtimeCommandIsReplayableQuery(i.command.name),R=f?ephemeralQueryAccept(i):await this.journal.acceptMessageRequest({operationId:i.operationId,command:i.command.name,paramsHash:i.paramsHash,runtimeEpoch:i.dispatchEpoch,requestMessageId:i.requestMessageId,requestHash:i.requestHash});d.mark("journal-accept");const y=E?v:R,w=f?"execute":decideMessageServiceRecovery(u.snapshot,i,y,E);if("already_terminal"===w)return void await l();if(!CORE_RECOVERY_DECISIONS.has(w))return f||await this.markOutcomeUnknownIfMutable(R),await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(i,new RuntimeCommandError("OUTCOME_UNKNOWN",`Types recovery policy requires ${w}; this runtime cannot safely replay Core`),(new Date).toISOString())}),void await l();if(await this.verifier.refresh(),d.mark("verifier-refresh"),!s)return E?await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(i,new RuntimeCommandError("OUTCOME_UNKNOWN","retained started proof has no live execution grant"),(new Date).toISOString())}):await this.reject(i,"invalid_execution_grant",t),void await l();this.verifier.verifyAndDecodeGrant(s)||await this.verifier.refresh(!0);const _=()=>c.abort();let g;a.addEventListener("abort",_,{once:!0});try{g=await verifyAndCreateMessageServiceCoreExecutionAttempt({request:i,executionGrant:s,runtimeEpoch:t.runtimeEpoch,lease:t,verifier:this.verifier,allowExpiredGrant:E,abortSignal:c.signal,resolvePorts:async()=>await this.ports.resolve({request:i,executionGrant:s,command:i.command,getLease:()=>this.currentLease(t),...this.journalLineage(),journalRecord:R,abortSignal:c.signal})})}catch(e){if(a.removeEventListener("abort",_),c.abort(),!(e instanceof RuntimeResourceResolutionError))throw e;if("transient"===e.kind)return;return E?(f||await this.markOutcomeUnknownIfMutable(R),await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(i,new RuntimeCommandError("OUTCOME_UNKNOWN","eager resources cannot be reconstructed after retained started proof"),(new Date).toISOString())})):await this.reject(i,"integrity_mismatch"===e.kind?"resource_integrity_mismatch":"resource_resolution_rejected",t),void await l()}if(!g.ok)return a.removeEventListener("abort",_),c.abort(),E?(f||await this.markOutcomeUnknownIfMutable(R),await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:failurePayload(i,new RuntimeCommandError("OUTCOME_UNKNOWN","execution grant cannot be revalidated after retained started proof"),(new Date).toISOString())})):await this.reject(i,"invalid_execution_grant",t),void await l();if(!h||"prepared"!==R.phase&&"started"!==R.phase||c.abort(),c.signal.aborted&&!E)return a.removeEventListener("abort",_),await this.reject(i,"cancelled_before_dispatch",t),void await l();d.mark("attempt"),E?this.currentLease(t):(await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),executionGrant:s,type:RUNTIME_MESSAGE_TYPES.started,payload:{...runtimeMessageBase(i),executionMode:"start",executionGrantHash:i.executionGrantHash,handlerIdentity:t.handlerIdentity,claimedAt:R.messageBinding?.acceptedAt??R.updatedAt}}),d.mark("append-started"));const S=this.dispatcher.dispatch(i.command,g.context);S.completion.catch(()=>{}),o(()=>{c.abort(),S.cancel()}),c.signal.aborted&&S.cancel();const M=this.forwardProgress(i,S.progress,t).catch(()=>{});let N,O=!1;try{if(("mcp/set"===i.method||"mcp/unset"===i.method)&&hasEffectReceiptHandoff(S)){const e=await S.effectCommitted;if(e){if(e.operationId!==i.operationId||e.method!==i.command.name)throw new RuntimeCommandError("OUTCOME_UNKNOWN","Core MCP receipt correlation mismatch");const a=runtimeMessageHash(RUNTIME_HASH_DOMAINS.coreResult,{method:i.method,result:e.result}),o={schemaVersion:1,operationId:i.operationId,method:i.method,coreResultRef:`sha256:${a}`,coreResultHash:a};N=runtimeMessageHash(RUNTIME_HASH_DOMAINS.effectRecord,o),O=!0,await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.effectCommitted,payload:{...runtimeMessageBase(i),effectRecord:o,effectRecordHash:N,committedAt:e.committedAt}}),await S.acknowledgeEffectReceipt({operationId:i.operationId,method:i.command.name,effectRecordHash:N})}}const a=await S.completion;if(await M,d.mark("core"),f){const o=(new Date).toISOString();let r;try{r=sanitizeRuntimeServiceResult(i.method,a,g.context,void 0)}catch(e){throw new RuntimeCommandError("OUTCOME_UNKNOWN","committed Core result cannot be mapped safely",void 0,{cause:e})}const n=runtimeMessageHash(RUNTIME_HASH_DOMAINS.serviceResult,{method:i.method,result:r}),s=await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:{...runtimeMessageBase(i),outcome:"succeeded",response:{jsonrpc:"2.0",id:i.request.id,result:r},serviceResultHash:n,completedAt:o}});return d.mark("append-final"),this.observeRequestTerminalAccepted(e.deliveryId,s.message),await l(),void this.observeRequestAcknowledged(e.deliveryId,s.message)}const o=await this.journal.get(i.operationId);if(d.mark("journal-after-core"),!o||!isCommittedCorePhase(o.phase))throw new RuntimeCommandError("OUTCOME_UNKNOWN","Core completed without a committed local journal record");const r=o.updatedAt;let n,s;if("query"!==RUNTIME_INVOCATION_RECOVERY_CLASSES[i.method]){const e=isAgentProjectionMethod(i.method),s=S.getSnapshot().projection,c=o.agentProjectionIntent??o.agentProjectionPreparationFailure;if(e&&!c)throw new RuntimeCommandError("OUTCOME_UNKNOWN","agent effect committed without an atomic projection preparation record");if(!N&&"session/clear"!==i.method){const e=c?.coreResultHash??runtimeMessageHash(RUNTIME_HASH_DOMAINS.coreResult,{method:i.method,result:a}),n=o.agentProjectionIntent?.projectionRevision??(methodRequiresProjectionRevision(i.method)?s?.revision??`${Math.max(0,o.revision)}`:void 0),l={schemaVersion:1,operationId:i.operationId,method:i.method,coreResultRef:`sha256:${e}`,coreResultHash:e,...n?{projectionRevision:n}:{}};N=runtimeMessageHash(RUNTIME_HASH_DOMAINS.effectRecord,l),O=!0,await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.effectCommitted,payload:{...runtimeMessageBase(i),effectRecord:l,effectRecordHash:N,committedAt:r}}),d.mark("append-effect")}let u=e?await awaitRuntimeProjection(S):s;if("session/set_model"===i.method&&"synced"!==u?.state&&(u=await this.projectSessionModelAfterEffect(i,g.context,o,u),d.mark("set-model-projection")),e&&o.agentProjectionIntent&&(!u||u.revision!==o.agentProjectionIntent.projectionRevision))throw new RuntimeCommandError("OUTCOME_UNKNOWN","agent projection receipt revision mismatch");if("pending"===u?.state)return void await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.projectionPending,payload:{...runtimeMessageBase(i),revision:u.revision}});if("synced"===u?.state&&await this.publishProjectionSynced(i,t,{...u,state:"synced"}),"blocked"===u?.state){await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.projectionBlocked,payload:{...runtimeMessageBase(i),revision:u.revision,errorCode:"PROJECTION_BLOCKED"}});const e=RUNTIME_ERROR_DESCRIPTORS.PROJECTION_BLOCKED;return await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:{...runtimeMessageBase(i),outcome:"projection_blocked",response:{jsonrpc:"2.0",id:i.request.id,error:{code:e.jsonRpcCode,message:"PROJECTION_BLOCKED",data:{code:"PROJECTION_BLOCKED",operationId:i.operationId,effectState:"committed",retryMode:e.retryMode}}},effectRecordHash:N,completedAt:r}}),void await l()}n=e?u?.platformAgentId:void 0}try{s=sanitizeRuntimeServiceResult(i.method,a,g.context,n)}catch(e){throw new RuntimeCommandError("OUTCOME_UNKNOWN","committed Core result cannot be mapped safely",void 0,{cause:e})}const c=runtimeMessageHash(RUNTIME_HASH_DOMAINS.serviceResult,{method:i.method,result:s});O=!0;const u=await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:{...runtimeMessageBase(i),outcome:"succeeded",response:{jsonrpc:"2.0",id:i.request.id,result:s},serviceResultHash:c,...N?{effectRecordHash:N}:{},completedAt:r}});if(d.mark("append-final"),this.observeRequestTerminalAccepted(e.deliveryId,u.message),("mcp/set"===i.method||"mcp/unset"===i.method)&&hasEffectReceiptHandoff(S)&&"function"==typeof S.acknowledgeTerminalReceipt){if(!N)throw new RuntimeCommandError("OUTCOME_UNKNOWN","MCP terminal response lacks its committed effect hash");await S.acknowledgeTerminalReceipt({operationId:i.operationId,method:i.command.name,effectRecordHash:N,terminalMessageId:u.message.message_id})}await l(),this.observeRequestAcknowledged(e.deliveryId,u.message)}catch(e){const a=await this.journal.get(i.operationId);if(a&&isCommittedCorePhase(a.phase)&&O)throw e;const o=!a||!isCommittedCorePhase(a.phase)||e instanceof RuntimeCommandError&&"OUTCOME_UNKNOWN"===e.code?e:new RuntimeCommandError("OUTCOME_UNKNOWN","Core effect committed before terminal mapping",void 0,{cause:e});this.observeRequestFailure(i.operationId,i.method,o);const r=failurePayload(i,o,a?.updatedAt??(new Date).toISOString());await this.channel.append({operationId:i.operationId,lease:this.currentLease(t),type:RUNTIME_MESSAGE_TYPES.final,payload:r}),d.mark("append-terminal-failure"),await l()}finally{d.finish(),c.abort(),a.removeEventListener("abort",_)}}async handlePoison(e,t,a){this.currentLease(a);(await this.poisonJournal.record({delivery:e,reason:durablePoisonReason(t),limit:this.options.poisonDeliveryLimit??3})).terminal&&await this.channel.acknowledge({deliveryIds:[e.deliveryId],lease:this.currentLease(a)})}observeRequestTerminalAccepted(e,t){try{this.options.onRequestTerminalAccepted?.({deliveryId:e,message:t})}catch{}}observeRequestAcknowledged(e,t){try{this.options.onRequestAcknowledged?.({deliveryId:e,message:t})}catch{}}async forwardProgress(e,t,a){for await(const o of t)await this.channel.append({operationId:e.operationId,lease:this.currentLease(a),type:RUNTIME_MESSAGE_TYPES.progress,payload:{...runtimeMessageBase(e),phase:o.phase,progress:o}})}async reject(e,t,a){await this.channel.append({operationId:e.operationId,lease:this.currentLease(a),type:RUNTIME_MESSAGE_TYPES.final,payload:prestartFailurePayload(e,t)})}async markOutcomeUnknownIfMutable(e){"prepared"!==e.phase&&"started"!==e.phase||await this.journal.transition({operationId:e.operationId,expectedRevision:e.revision,phase:"outcome_unknown",errorCode:"OUTCOME_UNKNOWN"})}async projectSessionModelAfterEffect(e,t,a,o){const r=Object.freeze({state:"pending",revision:o?.revision??`${Math.max(0,a.revision)}`}),n=e.command;if("session.setModel"!==n.name||"conversation"!==n.context.scope)return r;const i=t.sessionModelProjection;if(!i)return r;try{await i.project({conversationId:n.context.conversation.runtimeConversationUid,modelOverrideId:n.params.modelOverrideId});const e=Object.freeze({state:"synced",revision:r.revision});try{const t=await this.journal.get(a.operationId)??a;if("projection_committed"===t.phase&&"synced"===t.projectionReceipt?.snapshot.state)return Object.freeze({state:"synced",revision:t.projectionReceipt.snapshot.revision});await this.journal.transition({operationId:t.operationId,expectedRevision:t.revision,phase:"projection_committed",projectionSnapshot:e})}catch{}return e}catch(e){return this.observeDeliveryError(e),r}}async publishProjectionSynced(e,t,a){const o=this.currentLease(t),r=await this.channel.history({operationId:e.operationId,lease:o});if("found"===r.status&&"synced"===r.snapshot.projectionState)return;const n={...runtimeMessageBase(e),revision:a.revision};("found"!==r.status||"reserved"===r.snapshot.projectionState||"pending"!==r.snapshot.projectionState&&void 0===r.snapshot.projectionPending)&&await this.channel.append({operationId:e.operationId,lease:o,type:RUNTIME_MESSAGE_TYPES.projectionPending,payload:n}),await this.channel.append({operationId:e.operationId,lease:o,type:RUNTIME_MESSAGE_TYPES.projectionSynced,payload:{...n,...a.platformAgentId?{platformAgentId:a.platformAgentId}:{}}})}journalLineage(){return this.options.getJournalLineage?.()??{journalStoreId:this.options.journalStoreId,journalGeneration:this.options.journalGeneration}}currentLease(e){const t=this.getLease();if(!t||t.instanceId!==e.instanceId||t.leaseId!==e.leaseId||t.runtimeEpoch!==e.runtimeEpoch||t.handlerIdentity!==e.handlerIdentity||!Number.isFinite(Date.parse(t.leaseExpiresAt))||Date.parse(t.leaseExpiresAt)<=Date.now())throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","runtime message lease changed");return t}}function ephemeralQueryAccept(e){return{operationId:e.operationId,command:e.command.name,paramsHash:e.paramsHash,runtimeEpoch:e.dispatchEpoch,phase:"prepared",revision:1,updatedAt:(new Date).toISOString(),messageBinding:{requestMessageId:e.requestMessageId,requestHash:e.requestHash,acceptedAt:(new Date).toISOString()}}}function durablePoisonReason(e){const t=e.replace(/[^a-z0-9_:.-]+/gi,"_").replace(/^_+|_+$/g,"").slice(0,256);if(!t)throw new Error("poison reason is empty");return t}function isCommittedCorePhase(e){return"effect_committed"===e||"projection_committed"===e}const CORE_RECOVERY_DECISIONS=new Set(["execute","resume","replay_effect_committed","resume_projection","publish_committed_result","publish_projected_result","publish_terminal_result"]);function decideMessageServiceRecovery(e,t,a,o){const r=RUNTIME_INVOCATION_PARITY_ENTRIES.find(e=>e.acpMethod===t.method),n=e.terminal?"terminal":"blocked"===e.projectionState?"projection_blocked":"synced"===e.projectionState?"projection_synced":"pending"===e.projectionState?"projection_pending":e.effectCommitted?"runtime_committed":o?"running":"queued",i="failed"===a?.phase||"outcome_unknown"===a?.phase?"terminal":a?.phase,s=a&&a.runtimeEpoch===t.dispatchEpoch&&(void 0===a.messageBinding||a.messageBinding.requestMessageId===t.requestMessageId&&a.messageBinding.requestHash===t.requestHash)?"continuous":"discontinuous";return reduceRuntimeRecoveryPolicy({recoveryClass:r?.recoveryClass??RUNTIME_INVOCATION_RECOVERY_CLASSES[t.method],projectionRequired:"mcp/set"===t.method||"mcp/unset"===t.method||(r?.projectionRequired??!1),messageServicePhase:n,executionBoundaryCrossed:o,lineageContinuity:s,journalState:a?"available":"unavailable",...i?{journalPhase:i}:{}})}export function sanitizeRuntimeServiceResult(e,t,a,o){if("session/clear"===e)return serviceClearResult(t,a?.historyBoundary);if("session/set_model"===e)return serviceSetModelResult(t,a);if(!(e in SERVICE_CANONICAL_COMMAND_NAMES))return t;const r="cron/status"===e&&record(t)?{enabled:t.enabled,jobCount:t.jobCount,..."number"==typeof t.nextWakeAtMs?{nextWakeAtMs:t.nextWakeAtMs}:{}}:t;return mapCanonicalResultToService(e,r,{...o?{platformAgentId:o}:{},classifySkillOrigin:e=>e.bundled?{origin:"bundled",slug:e.slug}:{origin:"legacy_runtime",slug:e.slug},resolveMcpView:e=>({name:e.name,transport:e.transport,origin:"legacy_runtime",...void 0===e.connected?{}:{connected:e.connected},...void 0===e.connectionTimeoutMs?{}:{connectionTimeoutMs:e.connectionTimeoutMs}}),sanitizeDiagnostic:e=>/^[A-Z][A-Z0-9_]{0,63}$/.test(e)?e:"RUNTIME_EXECUTION_FAILED"})}function serviceClearResult(e,t){if(!record(e)||!0!==e.cleared||"string"!=typeof e.historyGeneration||!t||"message-service"!==t.kind)throw new RuntimeCommandError("OUTCOME_UNKNOWN","committed clear result lacks its Message Service receipt");const a=t;if(!a.committedIntentId)throw new RuntimeCommandError("OUTCOME_UNKNOWN","Message Service clear receipt is unavailable");return{...e,clearIntentId:a.committedIntentId()}}function serviceSetModelResult(e,t){if(!record(e)||"string"!=typeof e.effectiveModelId||!t)throw new RuntimeCommandError("OUTCOME_UNKNOWN","committed set_model result is invalid");const a=t.verifiedMessageGrant?.claims.command;if(!a||"session.setModel"!==a.name||"conversation"!==a.context.scope)throw new RuntimeCommandError("OUTCOME_UNKNOWN","set_model Service target receipt is unavailable");const o=a.params.modelOverrideId;return{conversationId:a.context.conversation.runtimeConversationUid,...null===o?{defaultModelId:e.effectiveModelId}:{},modelOverrideId:o,effectiveModelId:e.effectiveModelId,effectState:"committed",projectionState:"synced",operationId:t.operationId}}function isAgentProjectionMethod(e){return"agent/create"===e||"agent/update"===e||"agent/delete"===e||"agent/applyTemplate"===e}function methodRequiresProjectionRevision(e){return isAgentProjectionMethod(e)||"session/set_model"===e}function record(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}function sameLeaseBinding(e,t){return e.instanceId===t.instanceId&&e.leaseId===t.leaseId&&e.handlerIdentity===t.handlerIdentity&&e.runtimeEpoch===t.runtimeEpoch}function failurePayload(e,t,a){const o=t instanceof RuntimeCommandError?t.code:"RUNTIME_EXECUTION_FAILED",r=o in RUNTIME_ERROR_DESCRIPTORS?o:"RUNTIME_EXECUTION_FAILED",n="OUTCOME_UNKNOWN"===r||"INSTANCE_EPOCH_MISMATCH"===r?"outcome_unknown":"COMMAND_EXPIRED"===r?"expired":"OPERATION_CANCELLED"===r?"cancelled":"failed",i="outcome_unknown"===n?"OUTCOME_UNKNOWN":r,s=RUNTIME_ERROR_DESCRIPTORS[i],d="outcome_unknown"===n?"outcome_unknown":n;return{...runtimeMessageBase(e),outcome:n,response:{jsonrpc:"2.0",id:e.request.id,error:{code:s.jsonRpcCode,message:i,data:{code:i,operationId:e.operationId,effectState:d,retryMode:s.retryMode}}},completedAt:a}}function prestartFailurePayload(e,t){const a="invalid_execution_grant"===t?"INVALID_EXECUTION_GRANT":"unsupported_method"===t?"METHOD_NOT_SUPPORTED":"authority_mismatch"===t?"INSTANCE_EPOCH_MISMATCH":"execution_deadline_exceeded"===t?"COMMAND_EXPIRED":"cancelled_before_dispatch"===t?"OPERATION_CANCELLED":"resource_resolution_rejected"===t?"INVALID_INVOCATION":"RUNTIME_EXECUTION_FAILED",o=RUNTIME_ERROR_DESCRIPTORS[a in RUNTIME_ERROR_DESCRIPTORS?a:"RUNTIME_EXECUTION_FAILED"],r="COMMAND_EXPIRED"===a?"expired":"OPERATION_CANCELLED"===a?"cancelled":"failed";return{...runtimeMessageBase(e),outcome:r,response:{jsonrpc:"2.0",id:e.request.id,error:{code:o.jsonRpcCode,message:a,data:{code:a,operationId:e.operationId,effectState:r,retryMode:o.retryMode}}},completedAt:(new Date).toISOString()}}function abortable(e,t){return t?t.aborted?Promise.resolve():new Promise((a,o)=>{const r=()=>a();t.addEventListener("abort",r,{once:!0}),e.then(()=>{t.removeEventListener("abort",r),a()},e=>{t.removeEventListener("abort",r),o(e)})}):e}function delay(e,t){return new Promise(a=>{if(t?.aborted)return a();const o=()=>{clearTimeout(r),a()},r=setTimeout(()=>{t?.removeEventListener("abort",o),a()},e);t?.addEventListener("abort",o,{once:!0})})}
@@ -1 +1 @@
1
- import{downloadNativeInputFile}from"./native-input-files.js";import{bindExistingRuntimeChatReply}from"@beeos-ai/cloud-agent-sdk";import{RUNTIME_HASH_DOMAINS}from"@beeos-ai/beeos-types/runtime";import{dispatchImInboundPrompt}from"../im-runtime-dispatch.js";import{prepareNativePromptInput}from"./native-prompt-preflight.js";import{verifyNativePromptAuthority}from"./native-prompt-authority.js";import{RuntimeCommandError}from"./runtime-command-dispatcher.js";import{runtimeCommandResultHash}from"./runtime-command-journal.js";import{runtimeMessageBase,runtimeMessageHash,semanticEqual}from"./runtime-message-channel-contract.js";import{openClawSessionModePatch}from"./runtime-session-control-service.js";export const nativePromptCancellationReason="chat_cancel:runtime_operation_cancel_requested";export class NativeCloudPromptBridge{options;constructor(e){if(this.options=e,"function"!=typeof e.host.resolveNativePromptSessionKey)throw new RuntimeCommandError("INVALID_PARAMS","native Core target resolver required");if("function"!=typeof e.host.prepareNativePromptModel)throw new RuntimeCommandError("INVALID_PARAMS","native Core model preparation required");if(!e.runBoundary)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run boundary required")}async execute(e){const{options:t}=this;if(await t.verifier.refresh(),!e.delivery.executionGrant)throw new RuntimeCommandError("INVALID_PARAMS","native grant missing");const a=e.delivery.message.payload,n="string"==typeof a.operationId?await t.journal.get(a.operationId):null,r=!!n&&"session.prompt"===n.command&&["started","effect_committed","projection_committed","failed"].includes(n.phase)&&n.paramsHash===a.paramsHash&&n.messageBinding?.requestMessageId===a.requestMessageId&&n.messageBinding?.requestHash===a.requestHash,i=verifyNativePromptAuthority({request:e.delivery.message.payload,decoded:t.verifier.verifyAndDecodeGrant(e.delivery.executionGrant),lease:e.lease,lineage:t.getLineage(),allowExpiredReadOnly:r}),{params:s}=i,o=i.request;try{const a=e.delivery.message;if("runtime_rpc_request"!==a.type||"completed"!==a.state||a.message_id!==o.requestMessageId||a.channel_id!==o.operationId||void 0!==a.in_reply_to)throw new RuntimeCommandError("INVALID_PARAMS","native envelope binding invalid");let n;void 0!==s.mode&&openClawSessionModePatch(s.mode);try{if(void 0!==s.mentions)throw new TypeError("native host per-prompt optional binding not implemented");n=prepareNativePromptInput(s.parts)}catch(e){throw new RuntimeCommandError(r?"OUTCOME_UNKNOWN":"INVALID_PARAMS","native host part unsupported",void 0,{cause:e})}const d=n.message;if(!t.host.activeRunAuthority)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native existing active-run authority unavailable");const m=()=>{const a=t.getLease(),n=t.getLineage();if(!a||a.instanceId!==e.lease.instanceId||a.handlerIdentity!==e.lease.handlerIdentity||a.runtimeEpoch!==s.runtimeLease.runtimeEpoch||a.leaseId!==s.runtimeLease.leaseId||n.journalStoreId!==s.runtimeLease.journalStoreId||n.journalGeneration!==s.runtimeLease.journalGeneration||Date.parse(a.leaseExpiresAt)<=Date.now())throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","native prompt attempt fenced")};m();const u=await t.channel.history({operationId:o.operationId,lease:e.lease,currentNativePrompt:i});if(m(),"found"!==u.status||u.snapshot.requestHash!==o.requestHash||u.snapshot.requestMessageId!==o.requestMessageId||!semanticEqual(u.snapshot.request.payload,o))throw new RuntimeCommandError("INVALID_PARAMS","native retained request mismatch");let l,p=await t.journal.get(o.operationId);if(m(),p&&("session.prompt"!==p.command||p.paramsHash!==o.paramsHash||p.runtimeEpoch!==s.runtimeLease.runtimeEpoch||p.messageBinding?.requestMessageId!==o.requestMessageId||p.messageBinding.requestHash!==o.requestHash))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native existing journal binding mismatch");if(!t.http.getMessage)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native task snapshot unavailable");try{l=await t.http.getMessage(t.getLease(),{conversationId:s.conversationId,messageId:s.taskRequestMessageId})}catch(e){throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original task snapshot unavailable",void 0,{cause:e})}if(m(),l.messageId!==s.taskRequestMessageId||l.conversationId!==s.conversationId||"chat_message"!==l.type||l.body!==d)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original task snapshot mismatch");const c=async()=>{if(!t.http.getMessage)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native single snapshot unavailable");m();const e=await t.http.getMessage(t.getLease(),{conversationId:s.conversationId,messageId:s.replyMessageId});return m(),this.assertReply(e,i),e};if(u.snapshot.started||p&&"prepared"!==p.phase){const e=u.snapshot.runBoundary?.finishedReceipt,a=u.snapshot.final;if(!(p&&["started","effect_committed","projection_committed","failed"].includes(p.phase)&&e&&"finished"===e.state&&e.activeRunRegistrationId===s.taskId&&a))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable MS finish audit or original result unavailable");const n=await c();if("agent_reply"!==n.type||n.state!==e.replyState||n.stopReason!==e.replyStopReason||n.updatedAt!==e.replyUpdatedAt)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original terminal does not match finished audit");const r=this.terminal(n,i);if(a.payload.outcome!==r.outcome||"final_message"!==u.snapshot.terminalSource)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final outcome mismatch");const d=a.payload.response;if("2.0"!==d.jsonrpc||d.id!==o.request.id)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final RPC binding mismatch");const l=runtimeCommandResultHash(r.result);if(p.resultReceipt&&p.resultReceipt.resultHash!==l||void 0!==p.result&&!semanticEqual(p.result,r.result))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original result conflicts with local receipt");if(void 0===d.result)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original canonical result evidence unavailable");{const e=u.snapshot.effectCommitted?.payload,t=runtimeMessageHash(RUNTIME_HASH_DOMAINS.coreResult,{method:o.method,result:d.result});if("succeeded"!==r.outcome||void 0!==d.error||!semanticEqual(d.result,r.result)||!e||e.effectRecord.coreResultHash!==t||e.effectRecord.coreResultRef!==`sha256:${t}`||a.payload.effectRecordHash!==e.effectRecordHash||a.payload.serviceResultHash!==runtimeMessageHash(RUNTIME_HASH_DOMAINS.serviceResult,{method:o.method,result:d.result}))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final result hash evidence mismatch")}const h=d.result;return m(),"started"===p.phase&&(p=await t.journal.transition({operationId:o.operationId,expectedRevision:p.revision,phase:"succeeded"===r.outcome?"effect_committed":"failed",result:h}),m()),{request:o,outcome:r.outcome,result:h,replayedFinal:a}}if(n.files.length&&!t.inputFiles)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native authorized input file resolver unavailable");if(u.snapshot.terminal||e.signal.aborted||u.snapshot.cancelRequested||await t.journal.getCancellation(o.operationId))throw new RuntimeCommandError("OPERATION_CANCELLED","native prompt cancelled before effect");const h=await t.host.resolveNativePromptSessionKey(i,m);if(m(),p=await t.journal.acceptMessageRequest({operationId:o.operationId,command:"session.prompt",paramsHash:o.paramsHash,runtimeEpoch:s.runtimeLease.runtimeEpoch,requestMessageId:o.requestMessageId,requestHash:o.requestHash}),m(),"prepared"!==p.phase)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native task already started");let g;const v=await bindExistingRuntimeChatReply({authority:{currentLease:t.getLease},http:t.http,binding:{conversationId:s.conversationId,messageId:s.replyMessageId,taskRequestMessageId:s.taskRequestMessageId,assertAttempt:m,assertPreparedClear:e=>{if(m(),!g||e.activeRunRegistrationId!==g||e.historyGeneration!==i.historyGeneration||e.runtimeEpoch!==s.runtimeLease.runtimeEpoch)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native prepared clear does not freeze this registered attempt")},mutationKey:e=>`native-reply:${o.operationId}:${s.runtimeLease.journalStoreId}:${s.runtimeLease.journalGeneration}:${e}`}});if(m(),e.signal.aborted||await t.journal.getCancellation(o.operationId))throw new RuntimeCommandError("OPERATION_CANCELLED","native prompt cancelled before start");await t.channel.append({operationId:o.operationId,lease:t.getLease(),currentNativePrompt:i,executionGrant:e.delivery.executionGrant,type:"runtime_operation_started",payload:{...runtimeMessageBase(o),executionGrantHash:o.executionGrantHash,handlerIdentity:e.lease.handlerIdentity,executionMode:"start",claimedAt:p.updatedAt}}),m(),p=await t.journal.transition({operationId:o.operationId,expectedRevision:p.revision,phase:"started"}),m();const I=()=>{m();const e=t.getLease();return{leaseId:e.leaseId,handlerIdentity:e.handlerIdentity,runtimeEpoch:e.runtimeEpoch,runtimeLeaseCredential:e.runtimeLeaseCredential}},f={operationId:o.operationId,requestMessageId:o.requestMessageId,conversationId:i.command.context.conversation.runtimeConversationUid,historyGeneration:i.historyGeneration,runtimeRunId:s.runtimeRunId},R=await t.runBoundary.start({...f,lease:I()});if(m(),"registered"!==R.status||R.historyGeneration!==i.historyGeneration||R.activeRunRegistrationId!==s.taskId)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run start did not register the original task");g=R.activeRunRegistrationId;const N=new AbortController,w=()=>N.abort(e.signal.reason);if(e.signal.addEventListener("abort",w,{once:!0}),e.signal.aborted&&w(),e.setCancel(e=>N.abort(e)),await t.journal.getCancellation(o.operationId)&&N.abort(nativePromptCancellationReason),m(),N.signal.aborted)throw e.signal.removeEventListener("abort",w),new RuntimeCommandError("OUTCOME_UNKNOWN","native registered run stopped before host invocation");const y=[];let E;const C=JSON.parse((await v.opened()).rawText),O=C.parts?.length??0,M=async e=>{const t=await e;return m(),this.assertReply(t,i),E=t,t},_={id:v.id,get isTerminated(){return v.isTerminated},get parts(){return y},opened:async()=>({messageId:v.id,outcome:"bound"}),appendBody:e=>v.appendBody(e),setBody:e=>v.setBody(e),addPart:e=>{y.push(e),v.addPart(e)},replacePart:(e,t)=>{y[e]=t,v.replacePart(O+e,t)},appendToolResult:(e,t,a)=>{const n={type:"tool_result",tool_use_id:e,content:t,...a?{is_error:!0}:{}};y.push(n),v.addPart(n)},finalize:e=>M(v.finalize(e)),fail:e=>M(v.fail(e)),cancel:e=>M(v.cancel(e))},U={message:d,mediaPaths:[],mediaTypes:[]};let q,b;try{await dispatchImInboundPrompt({...t.host,runtimeRunId:s.runtimeRunId,nativeActiveRunRegistration:{runtimeConversationUid:f.conversationId,runtimeSessionKey:i.command.context.conversation.runtimeSessionKey,historyGeneration:R.historyGeneration,targetMessageId:s.taskRequestMessageId,runtimeRunId:s.runtimeRunId,activeRunRegistrationId:R.activeRunRegistrationId},assertNativeTarget:async()=>{if(await t.host.resolveNativePromptSessionKey(i,m)!==h)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native prompt target changed before host invocation")},prepareNativeModel:async e=>{m(),await t.host.prepareNativePromptModel(i,e,m),m();for(const e of n.files){if(!t.inputFiles)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native authorized input file resolver unavailable");const a=await t.inputFiles.resolve({operationId:o.operationId,requestMessageId:o.requestMessageId,paramsHash:o.paramsHash,partIndex:e.partIndex,lease:t.getLease(),signal:N.signal});m();const n=await downloadNativeInputFile({fileId:e.fileId,...a,signal:N.signal,assertAttempt:m});U.mediaPaths.push(n.path),U.mediaTypes.push(n.mimeType)}m()},onNativeRunCompletion:e=>{b=e},retainedStream:_,abortSignal:N.signal,inReplyTo:s.taskRequestMessageId,prompt:{channelId:s.conversationId,inboundMessageId:s.taskRequestMessageId,requestId:o.requestMessageId,selfPrincipalId:e.lease.instanceId,sessionKey:h,dispatchInput:U},client:{messages:{startStream(){throw new Error("native reply POST forbidden")},getEnvelope:async()=>({state:(await c()).state})},getSnapshot:()=>({connection:"connected",messages:{},conversations:{}})}})}catch(e){q=e}finally{e.signal.removeEventListener("abort",w)}if(!b&&q)throw q;if(!b||b.runtimeRunId!==s.runtimeRunId||b.token.sessionKey!==h)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native physical host completion unavailable");try{await b.completion}catch(e){throw new RuntimeCommandError("OUTCOME_UNKNOWN","native host/abort/drain did not converge",void 0,{cause:e})}if(m(),!E)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native kernel settled without verified original reply terminal",void 0,{cause:q});const T=this.terminal(E,i),A=await c();v.assertTerminalSnapshot(A);const P="completed"===A.state?"completed":"cancelled"===A.state?"cancelled":"failed",S=await t.runBoundary.finish({...f,activeRunRegistrationId:g,terminalState:P,source:"runtime",lease:I()});if(m(),"finished"!==S.status&&"idempotent"!==S.status||S.activeRunRegistrationId!==g)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run finish was not acknowledged");return await t.journal.transition({operationId:o.operationId,expectedRevision:p.revision,phase:"succeeded"===T.outcome?"effect_committed":"failed",result:T.result}),m(),{request:o,...T}}catch(e){throw new NativePromptExecutionFailure(o,e)}}assertReply(e,t){if(e.messageId!==t.params.replyMessageId||e.conversationId!==t.params.conversationId||e.replyTo!==t.params.taskRequestMessageId)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable reply binding mismatch")}terminal(e,t){if(!e.stopReason||!["completed","failed","refused","cancelled"].includes(e.state))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable terminal absent");const a="cancelled"===e.state&&"user_stop"===e.stopReason?"cancelled":"completed"===e.state&&"end_turn"===e.stopReason?"succeeded":"failed";return{outcome:a,result:{runtimeRunId:t.params.runtimeRunId,stopReason:e.stopReason,requestAborted:"cancelled"===e.state&&"user_stop"===e.stopReason,..."failed"===a?{error:e.body}:{}}}}}export class NativePromptExecutionFailure extends Error{request;failure;constructor(e,t){super(t instanceof Error?t.message:String(t),{cause:t}),this.request=e,this.failure=t}}
1
+ import{createNativeOutputFileAttempt}from"./native-output-file-attempt.js";import{downloadNativeInputFile}from"./native-input-files.js";import{bindExistingRuntimeChatReply}from"@beeos-ai/cloud-agent-sdk";import{RUNTIME_HASH_DOMAINS}from"@beeos-ai/beeos-types/runtime";import{dispatchImInboundPrompt}from"../im-runtime-dispatch.js";import{prepareNativePromptInput}from"./native-prompt-preflight.js";import{verifyNativePromptAuthority}from"./native-prompt-authority.js";import{RuntimeCommandError}from"./runtime-command-dispatcher.js";import{runtimeCommandResultHash}from"./runtime-command-journal.js";import{runtimeMessageBase,runtimeMessageHash,semanticEqual}from"./runtime-message-channel-contract.js";import{openClawSessionModePatch}from"./runtime-session-control-service.js";export const nativePromptCancellationReason="chat_cancel:runtime_operation_cancel_requested";export class NativeCloudPromptBridge{options;constructor(e){if(this.options=e,"function"!=typeof e.host.resolveNativePromptSessionKey)throw new RuntimeCommandError("INVALID_PARAMS","native Core target resolver required");if("function"!=typeof e.host.prepareNativePromptModel)throw new RuntimeCommandError("INVALID_PARAMS","native Core model preparation required");if(!e.runBoundary)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run boundary required")}async execute(e){const{options:t}=this;if(await t.verifier.refresh(),!e.delivery.executionGrant)throw new RuntimeCommandError("INVALID_PARAMS","native grant missing");const a=e.delivery.message.payload,n="string"==typeof a.operationId?await t.journal.get(a.operationId):null,r=!!n&&"session.prompt"===n.command&&["started","effect_committed","projection_committed","failed"].includes(n.phase)&&n.paramsHash===a.paramsHash&&n.messageBinding?.requestMessageId===a.requestMessageId&&n.messageBinding?.requestHash===a.requestHash,s=verifyNativePromptAuthority({request:e.delivery.message.payload,decoded:t.verifier.verifyAndDecodeGrant(e.delivery.executionGrant),lease:e.lease,lineage:t.getLineage(),allowExpiredReadOnly:r}),{params:i}=s,o=s.request;try{const a=e.delivery.message;if("runtime_rpc_request"!==a.type||"completed"!==a.state||a.message_id!==o.requestMessageId||a.channel_id!==o.operationId||void 0!==a.in_reply_to)throw new RuntimeCommandError("INVALID_PARAMS","native envelope binding invalid");let n;void 0!==i.mode&&openClawSessionModePatch(i.mode);try{if(void 0!==i.mentions)throw new TypeError("native host per-prompt optional binding not implemented");n=prepareNativePromptInput(i.parts)}catch(e){throw new RuntimeCommandError(r?"OUTCOME_UNKNOWN":"INVALID_PARAMS","native host part unsupported",void 0,{cause:e})}const d=n.message;if(!t.host.activeRunAuthority)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native existing active-run authority unavailable");const m=()=>{const a=t.getLease(),n=t.getLineage();if(!a||a.instanceId!==e.lease.instanceId||a.handlerIdentity!==e.lease.handlerIdentity||a.runtimeEpoch!==i.runtimeLease.runtimeEpoch||a.leaseId!==i.runtimeLease.leaseId||n.journalStoreId!==i.runtimeLease.journalStoreId||n.journalGeneration!==i.runtimeLease.journalGeneration||Date.parse(a.leaseExpiresAt)<=Date.now())throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","native prompt attempt fenced")};m();const u=await t.channel.history({operationId:o.operationId,lease:e.lease,currentNativePrompt:s});if(m(),"found"!==u.status||u.snapshot.requestHash!==o.requestHash||u.snapshot.requestMessageId!==o.requestMessageId||!semanticEqual(u.snapshot.request.payload,o))throw new RuntimeCommandError("INVALID_PARAMS","native retained request mismatch");let l,p=await t.journal.get(o.operationId);if(m(),p&&("session.prompt"!==p.command||p.paramsHash!==o.paramsHash||p.runtimeEpoch!==i.runtimeLease.runtimeEpoch||p.messageBinding?.requestMessageId!==o.requestMessageId||p.messageBinding.requestHash!==o.requestHash))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native existing journal binding mismatch");if(!t.http.getMessage)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native task snapshot unavailable");try{l=await t.http.getMessage(t.getLease(),{conversationId:i.conversationId,messageId:i.taskRequestMessageId})}catch(e){throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original task snapshot unavailable",void 0,{cause:e})}if(m(),l.messageId!==i.taskRequestMessageId||l.conversationId!==i.conversationId||"chat_message"!==l.type||l.body!==d)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original task snapshot mismatch");const c=async()=>{if(!t.http.getMessage)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native single snapshot unavailable");m();const e=await t.http.getMessage(t.getLease(),{conversationId:i.conversationId,messageId:i.replyMessageId});return m(),this.assertReply(e,s),e};if(u.snapshot.started||p&&"prepared"!==p.phase){const e=u.snapshot.runBoundary?.finishedReceipt,a=u.snapshot.final;if(!(p&&["started","effect_committed","projection_committed","failed"].includes(p.phase)&&e&&"finished"===e.state&&e.activeRunRegistrationId===i.taskId&&a))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable MS finish audit or original result unavailable");const n=await c();if("agent_reply"!==n.type||n.state!==e.replyState||n.stopReason!==e.replyStopReason||n.updatedAt!==e.replyUpdatedAt)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original terminal does not match finished audit");const r=this.terminal(n,s);if(a.payload.outcome!==r.outcome||"final_message"!==u.snapshot.terminalSource)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final outcome mismatch");const d=a.payload.response;if("2.0"!==d.jsonrpc||d.id!==o.request.id)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final RPC binding mismatch");const l=runtimeCommandResultHash(r.result);if(p.resultReceipt&&p.resultReceipt.resultHash!==l||void 0!==p.result&&!semanticEqual(p.result,r.result))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original result conflicts with local receipt");if(void 0===d.result)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original canonical result evidence unavailable");{const e=u.snapshot.effectCommitted?.payload,t=runtimeMessageHash(RUNTIME_HASH_DOMAINS.coreResult,{method:o.method,result:d.result});if("succeeded"!==r.outcome||void 0!==d.error||!semanticEqual(d.result,r.result)||!e||e.effectRecord.coreResultHash!==t||e.effectRecord.coreResultRef!==`sha256:${t}`||a.payload.effectRecordHash!==e.effectRecordHash||a.payload.serviceResultHash!==runtimeMessageHash(RUNTIME_HASH_DOMAINS.serviceResult,{method:o.method,result:d.result}))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final result hash evidence mismatch")}const h=d.result;return m(),"started"===p.phase&&(p=await t.journal.transition({operationId:o.operationId,expectedRevision:p.revision,phase:"succeeded"===r.outcome?"effect_committed":"failed",result:h}),m()),{request:o,outcome:r.outcome,result:h,replayedFinal:a}}if(n.files.length&&!t.inputFiles)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native authorized input file resolver unavailable");if(u.snapshot.terminal||e.signal.aborted||u.snapshot.cancelRequested||await t.journal.getCancellation(o.operationId))throw new RuntimeCommandError("OPERATION_CANCELLED","native prompt cancelled before effect");const h=await t.host.resolveNativePromptSessionKey(s,m);if(m(),p=await t.journal.acceptMessageRequest({operationId:o.operationId,command:"session.prompt",paramsHash:o.paramsHash,runtimeEpoch:i.runtimeLease.runtimeEpoch,requestMessageId:o.requestMessageId,requestHash:o.requestHash}),m(),"prepared"!==p.phase)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native task already started");let g;const v=await bindExistingRuntimeChatReply({authority:{currentLease:t.getLease},http:t.http,binding:{conversationId:i.conversationId,messageId:i.replyMessageId,taskRequestMessageId:i.taskRequestMessageId,assertAttempt:m,assertPreparedClear:e=>{if(m(),!g||e.activeRunRegistrationId!==g||e.historyGeneration!==s.historyGeneration||e.runtimeEpoch!==i.runtimeLease.runtimeEpoch)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native prepared clear does not freeze this registered attempt")},mutationKey:e=>`native-reply:${o.operationId}:${i.runtimeLease.journalStoreId}:${i.runtimeLease.journalGeneration}:${e}`}});if(m(),e.signal.aborted||await t.journal.getCancellation(o.operationId))throw new RuntimeCommandError("OPERATION_CANCELLED","native prompt cancelled before start");await t.channel.append({operationId:o.operationId,lease:t.getLease(),currentNativePrompt:s,executionGrant:e.delivery.executionGrant,type:"runtime_operation_started",payload:{...runtimeMessageBase(o),executionGrantHash:o.executionGrantHash,handlerIdentity:e.lease.handlerIdentity,executionMode:"start",claimedAt:p.updatedAt}}),m(),p=await t.journal.transition({operationId:o.operationId,expectedRevision:p.revision,phase:"started"}),m();const I=()=>{m();const e=t.getLease();return{leaseId:e.leaseId,handlerIdentity:e.handlerIdentity,runtimeEpoch:e.runtimeEpoch,runtimeLeaseCredential:e.runtimeLeaseCredential}},R={operationId:o.operationId,requestMessageId:o.requestMessageId,conversationId:s.command.context.conversation.runtimeConversationUid,historyGeneration:s.historyGeneration,runtimeRunId:i.runtimeRunId},f=await t.runBoundary.start({...R,lease:I()});if(m(),"registered"!==f.status||f.historyGeneration!==s.historyGeneration||f.activeRunRegistrationId!==i.taskId)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run start did not register the original task");g=f.activeRunRegistrationId;const N=new AbortController,w=()=>N.abort(e.signal.reason);if(e.signal.addEventListener("abort",w,{once:!0}),e.signal.aborted&&w(),e.setCancel(e=>N.abort(e)),await t.journal.getCancellation(o.operationId)&&N.abort(nativePromptCancellationReason),m(),N.signal.aborted)throw e.signal.removeEventListener("abort",w),new RuntimeCommandError("OUTCOME_UNKNOWN","native registered run stopped before host invocation");const y=[];let E;const O=JSON.parse((await v.opened()).rawText),C=O.parts?.length??0,M=async e=>{const t=await e;return m(),this.assertReply(t,s),E=t,t},_={id:v.id,get isTerminated(){return v.isTerminated},get parts(){return y},opened:async()=>({messageId:v.id,outcome:"bound"}),appendBody:e=>v.appendBody(e),setBody:e=>v.setBody(e),addPart:e=>{y.push(e),v.addPart(e)},replacePart:(e,t)=>{y[e]=t,v.replacePart(C+e,t)},appendToolResult:(e,t,a)=>{const n={type:"tool_result",tool_use_id:e,content:t,...a?{is_error:!0}:{}};y.push(n),v.addPart(n)},finalize:e=>M(v.finalize(e)),fail:e=>M(v.fail(e)),cancel:e=>M(v.cancel(e))},U={message:d,mediaPaths:[],mediaTypes:[]};let q,b;const A=createNativeOutputFileAttempt({operationId:o.operationId,requestMessageId:o.requestMessageId,paramsHash:o.paramsHash,activeRunRegistrationId:g,getLease:()=>(m(),t.getLease()),assertAttempt:m,signal:N.signal});try{await dispatchImInboundPrompt({...t.host,runtimeRunId:i.runtimeRunId,onNativeAgentRunStart:e=>A.bindHostRun(e),nativeActiveRunRegistration:{runtimeConversationUid:R.conversationId,runtimeSessionKey:s.command.context.conversation.runtimeSessionKey,historyGeneration:f.historyGeneration,targetMessageId:i.taskRequestMessageId,runtimeRunId:i.runtimeRunId,activeRunRegistrationId:f.activeRunRegistrationId},assertNativeTarget:async()=>{if(await t.host.resolveNativePromptSessionKey(s,m)!==h)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native prompt target changed before host invocation")},prepareNativeModel:async e=>{m(),await t.host.prepareNativePromptModel(s,e,m),m();for(const e of n.files){if(!t.inputFiles)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native authorized input file resolver unavailable");const a=await t.inputFiles.resolve({operationId:o.operationId,requestMessageId:o.requestMessageId,paramsHash:o.paramsHash,partIndex:e.partIndex,lease:t.getLease(),signal:N.signal});m();const n=await downloadNativeInputFile({fileId:e.fileId,...a,signal:N.signal,assertAttempt:m});U.mediaPaths.push(n.path),U.mediaTypes.push(n.mimeType)}m()},onNativeRunCompletion:e=>{b=e},retainedStream:_,abortSignal:N.signal,inReplyTo:i.taskRequestMessageId,prompt:{channelId:i.conversationId,inboundMessageId:i.taskRequestMessageId,requestId:o.requestMessageId,selfPrincipalId:e.lease.instanceId,sessionKey:h,dispatchInput:U},client:{messages:{startStream(){throw new Error("native reply POST forbidden")},getEnvelope:async()=>({state:(await c()).state})},getSnapshot:()=>({connection:"connected",messages:{},conversations:{}})}})}catch(e){q=e}finally{A.close(),e.signal.removeEventListener("abort",w)}if(!b&&q)throw q;if(!b||b.runtimeRunId!==i.runtimeRunId||b.token.sessionKey!==h)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native physical host completion unavailable");try{await b.completion}catch(e){throw new RuntimeCommandError("OUTCOME_UNKNOWN","native host/abort/drain did not converge",void 0,{cause:e})}if(m(),!E)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native kernel settled without verified original reply terminal",void 0,{cause:q});const T=this.terminal(E,s),S=await c();v.assertTerminalSnapshot(S);const P="completed"===S.state?"completed":"cancelled"===S.state?"cancelled":"failed",H=await t.runBoundary.finish({...R,activeRunRegistrationId:g,terminalState:P,source:"runtime",lease:I()});if(m(),"finished"!==H.status&&"idempotent"!==H.status||H.activeRunRegistrationId!==g)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run finish was not acknowledged");return await t.journal.transition({operationId:o.operationId,expectedRevision:p.revision,phase:"succeeded"===T.outcome?"effect_committed":"failed",result:T.result}),m(),{request:o,...T}}catch(e){throw new NativePromptExecutionFailure(o,e)}}assertReply(e,t){if(e.messageId!==t.params.replyMessageId||e.conversationId!==t.params.conversationId||e.replyTo!==t.params.taskRequestMessageId)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable reply binding mismatch")}terminal(e,t){if(!e.stopReason||!["completed","failed","refused","cancelled"].includes(e.state))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable terminal absent");const a="cancelled"===e.state&&"user_stop"===e.stopReason?"cancelled":"completed"===e.state&&"end_turn"===e.stopReason?"succeeded":"failed";return{outcome:a,result:{runtimeRunId:t.params.runtimeRunId,stopReason:e.stopReason,requestAborted:"cancelled"===e.state&&"user_stop"===e.stopReason,..."failed"===a?{error:e.body}:{}}}}}export class NativePromptExecutionFailure extends Error{request;failure;constructor(e,t){super(t instanceof Error?t.message:String(t),{cause:t}),this.request=e,this.failure=t}}
@@ -0,0 +1 @@
1
+ const runs=new Map,tools=new Map,consumed=new Set;export function createNativeOutputFileAttempt(t){let e,o=!0;const s={...t,assertAttempt(){if(!o)throw new Error("native output file attempt finished");t.signal.throwIfAborted(),t.assertAttempt();const e=t.getLease();if(!e.runtimeLeaseCredential||!Number.isFinite(Date.parse(e.leaseExpiresAt))||Date.parse(e.leaseExpiresAt)<=Date.now())throw new Error("native output file lease fenced")},getLease:()=>(s.assertAttempt(),t.getLease())};return{bindHostRun(t){if(s.assertAttempt(),!t||void 0!==e||runs.has(t))throw new Error("native output file Host run binding ambiguous");e=t,runs.set(t,s)},close(){o=!1,e&&runs.get(e)===s&&runs.delete(e);for(const[t,e]of tools)e.assertAttempt===s.assertAttempt&&tools.delete(t);for(const e of consumed)e.startsWith(t.operationId+"\0")&&consumed.delete(e)}}}export function prepareNativeOutputTool(t,e){if(!t||!e)throw new Error("native output file trusted Host tool binding missing");const o=runs.get(t);if(!o)throw new Error("native output file trusted run missing");o.assertAttempt();const s=o.operationId+"\0"+e;if(tools.has(e)||consumed.has(s))throw new Error("native output file tool binding ambiguous or consumed");tools.set(e,{...o,toolCallId:e})}export function consumeNativeOutputTool(t){const e=tools.get(t);if(tools.delete(t),!e)throw new Error("native output file tool capability missing");return e.assertAttempt(),consumed.add(e.operationId+"\0"+t),e}
@@ -1 +1 @@
1
- import{constants}from"node:fs";import{access,stat}from"node:fs/promises";import{uploadLocalFile}from"./upload-file.js";import{isBeeosFileUri}from"../files/beeos-file-uri.js";export const BEEOS_UPLOAD_TOOL_NAME="beeos_upload_file";export const BEEOS_UPLOAD_TOOL_DESCRIPTION="Upload 1-5 local files from this machine to the user via the BeeOS platform. Accepts only local filesystem paths; never pass beeos-file:// URIs because they are already BeeOS platform resources. If the call succeeds, the files are already delivered to the user — do not use any other tool to send them again. Upload modified deliverables again even if the same path was uploaded earlier; unchanged contents may reuse an existing platform file. Any file type is accepted: text, images, documents, PDFs, archives, binaries.";export const BEEOS_UPLOAD_TOOL_SCHEMA={title:"BeeOS file upload",type:"object",description:BEEOS_UPLOAD_TOOL_DESCRIPTION,additionalProperties:!1,required:["paths"],properties:{paths:{type:"array",minItems:1,maxItems:5,description:"Local filesystem paths (1-5). Absolute or workspace-relative. Do not pass beeos-file:// URIs.",items:{type:"string",minLength:1,description:"Single local filesystem path, not a beeos-file:// URI."}}}};const MAX_PATHS=5,REQUEST_TIMEOUT_MS=12e4,MAX_CONCURRENCY=3,BEEOS_FILE_URI_UPLOAD_ERROR="beeos-file:// is already a BeeOS platform file URI, not a local path. Do not upload it; display it directly.";async function runWithConcurrency(e,t){const r=new Array(e.length);let a=0;async function o(){for(;a<e.length;){const t=a++;r[t]=await e[t]()}}const s=[];for(let r=0;r<Math.min(t,e.length);r++)s.push(o());return await Promise.all(s),r}async function validateFiles(e){return Promise.all(e.map(async e=>{try{await access(e,constants.R_OK);return(await stat(e)).isFile()?{path:e,ok:!0}:{path:e,ok:!1,error:"not a regular file"}}catch(t){const r=t.code;let a;return a="ENOENT"===r?"file not found":"ENOTDIR"===r?"path component is not a directory":"EACCES"===r?"permission denied":t instanceof Error?t.message:String(t),{path:e,ok:!1,error:a}}}))}export async function executeUpload(e,t,r,a){const o=parseParams(e);if(!o.ok)return errorResult(o.error);if(!t.agentGatewayUrl)return errorResult("agentGatewayUrl not configured — file upload requires Agent Gateway access");if(!r)return errorResult("agent key pair not available — cannot sign upload requests");const s=t.agentGatewayUrl,i=o.paths,n=(await validateFiles(i)).find(e=>!e.ok);if(n)return errorResult(`${n.path}: ${n.error}`);const l=[],p=i.map(e=>async()=>{try{return await uploadSingleFile(e,s,r,a)}catch(t){if(a?.aborted)throw t;return l.push(`${e}: ${t instanceof Error?t.message:String(t)}`),null}}),c=(await runWithConcurrency(p,3)).filter(e=>null!==e);if(0===c.length)return errorResult(`All uploads failed: ${l.join("; ")}`);const u=c.map(e=>({uri:`beeos-file://${e.fileId}`,name:e.fileName,mimeType:e.mimeType,fileId:e.fileId})),f=c.length===i.length?`Uploaded ${c.length} file(s): ${u.map(e=>e.name).join(", ")}`:`Uploaded ${c.length}/${i.length} file(s): ${u.map(e=>e.name).join(", ")}. Failed: ${l.join("; ")}`,m={ok:!0,files:u};return{...m,content:[{type:"text",text:f},...u.map(e=>({type:"resource_link",uri:e.uri,name:e.name,mimeType:e.mimeType}))],output:m,result:m,details:m,isError:!1}}async function uploadSingleFile(e,t,r,a){const o=await uploadLocalFile(e,t,r,{signal:a,timeoutMs:12e4});return{fileId:o.fileId,downloadUrl:"",fileName:o.name,mimeType:o.mimeType,size:o.size}}function parseParams(e){if(!e||"object"!=typeof e)return{ok:!1,error:"params must be an object"};const t=e;if(Object.keys(t).filter(e=>"paths"!==e).length>0)return{ok:!1,error:"only paths is allowed"};if(!Array.isArray(t.paths))return{ok:!1,error:"paths must be an array"};if(t.paths.length<1)return{ok:!1,error:"paths must contain at least 1 item"};if(t.paths.length>5)return{ok:!1,error:"paths must contain no more than 5 items"};const r=[];for(let e=0;e<t.paths.length;e++){const a=t.paths[e];if("string"!=typeof a||""===a.trim())return{ok:!1,error:`paths[${e}] must be a non-empty string`};const o=a.trim();if(isBeeosFileUri(o))return{ok:!1,error:BEEOS_FILE_URI_UPLOAD_ERROR};r.push(o)}return{ok:!0,paths:r}}function errorResult(e){const t={ok:!1,error:e};return{...t,content:[{type:"text",text:e}],output:t,result:t,details:t,isError:!0}}
1
+ import{constants}from"node:fs";import{access,stat}from"node:fs/promises";import{uploadLocalFile,NativeOutputFilesError}from"./upload-file.js";import{isBeeosFileUri}from"../files/beeos-file-uri.js";export const BEEOS_UPLOAD_TOOL_NAME="beeos_upload_file";export const BEEOS_UPLOAD_TOOL_DESCRIPTION="Upload 1-5 local files from this machine to the user via the BeeOS platform. Accepts only local filesystem paths; never pass beeos-file:// URIs because they are already BeeOS platform resources. If the call succeeds, the files are already delivered to the user — do not use any other tool to send them again. Upload modified deliverables again even if the same path was uploaded earlier; unchanged contents may reuse an existing platform file. Any file type is accepted: text, images, documents, PDFs, archives, binaries.";export const BEEOS_UPLOAD_TOOL_SCHEMA={title:"BeeOS file upload",type:"object",description:BEEOS_UPLOAD_TOOL_DESCRIPTION,additionalProperties:!1,required:["paths"],properties:{paths:{type:"array",minItems:1,maxItems:5,description:"Local filesystem paths (1-5). Absolute or workspace-relative. Do not pass beeos-file:// URIs.",items:{type:"string",minLength:1,description:"Single local filesystem path, not a beeos-file:// URI."}}}};const MAX_PATHS=5,REQUEST_TIMEOUT_MS=12e4,MAX_CONCURRENCY=3,BEEOS_FILE_URI_UPLOAD_ERROR="beeos-file:// is already a BeeOS platform file URI, not a local path. Do not upload it; display it directly.";async function runWithConcurrency(e,t){const r=new Array(e.length);let a=0;async function o(){for(;a<e.length;){const t=a++;r[t]=await e[t]()}}const i=[];for(let r=0;r<Math.min(t,e.length);r++)i.push(o());return await Promise.all(i),r}async function validateFiles(e){return Promise.all(e.map(async e=>{try{await access(e,constants.R_OK);return(await stat(e)).isFile()?{path:e,ok:!0}:{path:e,ok:!1,error:"not a regular file"}}catch(t){const r=t.code;let a;return a="ENOENT"===r?"file not found":"ENOTDIR"===r?"path component is not a directory":"EACCES"===r?"permission denied":t instanceof Error?t.message:String(t),{path:e,ok:!1,error:a}}}))}export async function executeUpload(e,t,r,a,o){const i=parseParams(e);if(!i.ok)return errorResult(i.error);if(!t.agentGatewayUrl)return errorResult("agentGatewayUrl not configured — file upload requires Agent Gateway access");if(!r&&!o)return errorResult("agent key pair not available — cannot sign upload requests");const s=t.agentGatewayUrl,n=i.paths,l=(await validateFiles(n)).find(e=>!e.ok);if(l)return errorResult(`${l.path}: ${l.error}`);const p=[],u=n.map((e,t)=>async()=>{try{if(o){const r=await o(e,t);return{fileId:r.fileId,downloadUrl:"",fileName:r.name,mimeType:r.mimeType,size:r.size}}return await uploadSingleFile(e,s,r,a)}catch(t){if(a?.aborted)throw t;return p.push(o?t instanceof NativeOutputFilesError?t.message:"native output Files transport or local read failed":`${e}: ${t instanceof Error?t.message:String(t)}`),null}}),c=(await runWithConcurrency(u,3)).filter(e=>null!==e);if(0===c.length)return errorResult(`All uploads failed: ${p.join("; ")}`);const m=c.map(e=>({uri:`beeos-file://${e.fileId}`,name:e.fileName,mimeType:e.mimeType,fileId:e.fileId})),f=c.length===n.length?`Uploaded ${c.length} file(s): ${m.map(e=>e.name).join(", ")}`:`Uploaded ${c.length}/${n.length} file(s): ${m.map(e=>e.name).join(", ")}. Failed: ${p.join("; ")}`,d={ok:!0,files:m};return{...d,content:[{type:"text",text:f},...m.map(e=>({type:"resource_link",uri:e.uri,name:e.name,mimeType:e.mimeType}))],output:d,result:d,details:d,isError:!1}}async function uploadSingleFile(e,t,r,a){const o=await uploadLocalFile(e,t,r,{signal:a,timeoutMs:12e4});return{fileId:o.fileId,downloadUrl:"",fileName:o.name,mimeType:o.mimeType,size:o.size}}function parseParams(e){if(!e||"object"!=typeof e)return{ok:!1,error:"params must be an object"};const t=e;if(Object.keys(t).filter(e=>"paths"!==e).length>0)return{ok:!1,error:"only paths is allowed"};if(!Array.isArray(t.paths))return{ok:!1,error:"paths must be an array"};if(t.paths.length<1)return{ok:!1,error:"paths must contain at least 1 item"};if(t.paths.length>5)return{ok:!1,error:"paths must contain no more than 5 items"};const r=[];for(let e=0;e<t.paths.length;e++){const a=t.paths[e];if("string"!=typeof a||""===a.trim())return{ok:!1,error:`paths[${e}] must be a non-empty string`};const o=a.trim();if(isBeeosFileUri(o))return{ok:!1,error:BEEOS_FILE_URI_UPLOAD_ERROR};r.push(o)}return{ok:!0,paths:r}}function errorResult(e){const t={ok:!1,error:e};return{...t,content:[{type:"text",text:e}],output:t,result:t,details:t,isError:!0}}
@@ -1 +1 @@
1
- import{access,constants,readFile,stat}from"node:fs/promises";import{createHash}from"node:crypto";import{basename,extname,resolve}from"node:path";import{agentFetch}from"../agent-auth.js";import{noteUploadedDeliverable}from"./delivery-ledger.js";const DEFAULT_TIMEOUT_MS=3e4,UPLOAD_REUSE_TTL_MS=18e5,MAX_REUSED_UPLOADS=256,completedUploads=new Map;let _deps=null;export function setUploadDeps(e){_deps=e}export function getUploadDeps(){return _deps}export async function uploadLocalFile(e,t,a,r){await access(e,constants.R_OK);if(!(await stat(e)).isFile())throw new Error("not a regular file");const o=basename(e),s=r?.fileNameOverride??o,n=inferMimeType(s),i=await readFile(e);r?.signal?.throwIfAborted();const c=createHash("sha256").update(i).digest("hex"),p=JSON.stringify([t,Buffer.from(a.publicKey).toString("base64"),resolve(e),s,c]),l=Date.now();for(const[e,t]of completedUploads)t.expiresAt<=l&&completedUploads.delete(e);const d=completedUploads.get(p);if(d)return noteUploadedDeliverable(e),{...d.result};const m=AbortSignal.timeout(r?.timeoutMs??3e4),u=r?.signal?AbortSignal.any([r.signal,m]):m,f=`${t}/api/v1/agent/files`,g=await agentFetch(f+"/presign",a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({fileName:s,mimeType:n}),signal:u});if(!g.ok){const e=await g.text().catch(()=>g.statusText);throw new Error(`presign ${g.status}: ${e}`)}const x=await g.json(),w=await fetch(x.uploadUrl,{method:"PUT",headers:{"Content-Type":n},body:new Blob([i],{type:n}),signal:u});if(!w.ok)throw new Error(`S3 PUT failed: ${w.status}`);const v=await agentFetch(f+"/confirm",a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({fileId:x.fileId}),signal:u});if(!v.ok){const e=await v.text().catch(()=>v.statusText);throw new Error(`confirm ${v.status}: ${e}`)}const h=await v.json(),y={fileId:h.fileId,uri:`beeos-file://${h.fileId}`,name:h.fileName||s,mimeType:h.mimeType||n,size:h.size||i.byteLength};if(!y.fileId)throw new Error("confirm returned no fileId");return completedUploads.size>=256&&completedUploads.delete(completedUploads.keys().next().value),completedUploads.set(p,{result:y,expiresAt:Date.now()+18e5}),noteUploadedDeliverable(e),{...y}}function inferMimeType(e){switch(extname(e).toLowerCase()){case".txt":return"text/plain";case".md":return"text/markdown";case".json":return"application/json";case".html":return"text/html";case".css":return"text/css";case".js":case".mjs":case".cjs":return"text/javascript";case".ts":return"text/x.typescript";case".tsx":case".jsx":return"text/jsx";case".xml":return"application/xml";case".yaml":case".yml":return"application/yaml";case".toml":return"application/toml";case".pdf":return"application/pdf";case".doc":return"application/msword";case".docx":return"application/vnd.openxmlformats-officedocument.wordprocessingml.document";case".xls":return"application/vnd.ms-excel";case".xlsx":return"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";case".ppt":return"application/vnd.ms-powerpoint";case".pptx":return"application/vnd.openxmlformats-officedocument.presentationml.presentation";case".rtf":return"application/rtf";case".odt":return"application/vnd.oasis.opendocument.text";case".ods":return"application/vnd.oasis.opendocument.spreadsheet";case".odp":return"application/vnd.oasis.opendocument.presentation";case".png":return"image/png";case".jpg":case".jpeg":return"image/jpeg";case".gif":return"image/gif";case".webp":return"image/webp";case".svg":return"image/svg+xml";case".mp4":return"video/mp4";case".mov":return"video/quicktime";case".webm":return"video/webm";case".mkv":return"video/x-matroska";case".avi":return"video/x-msvideo";case".m4v":return"video/x-m4v";case".mp3":return"audio/mpeg";case".wav":return"audio/wav";case".flac":return"audio/flac";case".aac":return"audio/aac";case".ogg":return"audio/ogg";case".m4a":return"audio/mp4";case".csv":return"text/csv";case".zip":return"application/zip";case".tar":return"application/x-tar";case".gz":case".tgz":return"application/gzip";default:return"application/octet-stream"}}
1
+ import{cloudRuntimeTargetInstanceId}from"../runtime/runtime-production-authority.js";import{access,constants,readFile,stat}from"node:fs/promises";import{createHash}from"node:crypto";import{basename,extname,resolve}from"node:path";import{agentFetch}from"../agent-auth.js";import{noteUploadedDeliverable}from"./delivery-ledger.js";const DEFAULT_TIMEOUT_MS=3e4,UPLOAD_REUSE_TTL_MS=18e5,MAX_REUSED_UPLOADS=256,completedUploads=new Map;let _deps=null;export function setUploadDeps(e){_deps=e}export function getUploadDeps(){return _deps}export async function uploadLocalFile(e,t,a,r){if(cloudRuntimeTargetInstanceId(process.env))throw new Error("native output file trusted tool capability required");await access(e,constants.R_OK);if(!(await stat(e)).isFile())throw new Error("not a regular file");const i=basename(e),s=r?.fileNameOverride??i,o=inferMimeType(s),n=await readFile(e);r?.signal?.throwIfAborted();const p=createHash("sha256").update(n).digest("hex"),c=JSON.stringify([t,Buffer.from(a.publicKey).toString("base64"),resolve(e),s,p]),l=Date.now();for(const[e,t]of completedUploads)t.expiresAt<=l&&completedUploads.delete(e);const d=completedUploads.get(c);if(d)return noteUploadedDeliverable(e),{...d.result};const u=AbortSignal.timeout(r?.timeoutMs??3e4),m=r?.signal?AbortSignal.any([r.signal,u]):u,f=`${t}/api/v1/agent/files`,h=await agentFetch(f+"/presign",a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({fileName:s,mimeType:o}),signal:m});if(!h.ok){const e=await h.text().catch(()=>h.statusText);throw new Error(`presign ${h.status}: ${e}`)}const g=await h.json(),w=await fetch(g.uploadUrl,{method:"PUT",headers:{"Content-Type":o},body:new Blob([n],{type:o}),signal:m});if(!w.ok)throw new Error(`S3 PUT failed: ${w.status}`);const v=await agentFetch(f+"/confirm",a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({fileId:g.fileId}),signal:m});if(!v.ok){const e=await v.text().catch(()=>v.statusText);throw new Error(`confirm ${v.status}: ${e}`)}const y=await v.json(),x={fileId:y.fileId,uri:`beeos-file://${y.fileId}`,name:y.fileName||s,mimeType:y.mimeType||o,size:y.size||n.byteLength};if(!x.fileId)throw new Error("confirm returned no fileId");return completedUploads.size>=256&&completedUploads.delete(completedUploads.keys().next().value),completedUploads.set(c,{result:x,expiresAt:Date.now()+18e5}),noteUploadedDeliverable(e),{...x}}export class NativeOutputFilesError extends Error{}export async function uploadNativeOutputFile(e,t,a,r,i){a.assertAttempt(),await access(e,constants.R_OK);const s=await stat(e);if(!s.isFile()||s.size<=0||s.size>104857600)throw new Error("native output file size invalid");const o=await readFile(e);if(a.assertAttempt(),o.byteLength!==s.size)throw new Error("native output file changed while reading");const n=basename(e),p=inferMimeType(n),c=createHash("sha256").update(o).digest("hex"),l=createHash("sha256").update("beeos/native-output-file/v1\0"+a.operationId+"\0"+a.toolCallId+"\0"+r).digest("hex"),d=new URL(t);if(!["http:","https:"].includes(d.protocol)||d.username||d.password||"/"!==d.pathname||d.search||d.hash)throw new Error("native output Files origin invalid");const u=AbortSignal.any([a.signal,AbortSignal.timeout(3e4),...i?[i]:[]]),m={requestMessageId:a.requestMessageId,paramsHash:a.paramsHash,activeRunRegistrationId:a.activeRunRegistrationId,idempotencyKey:l},f=e=>!!e&&"object"==typeof e&&!Array.isArray(e),h=async(e,t)=>{a.assertAttempt();const r=a.getLease(),i=await fetch(new URL("/api/v1/internal/runtime/operations/"+encodeURIComponent(a.operationId)+"/output-files/"+e,d),{method:"POST",redirect:"error",signal:u,headers:{authorization:"Bearer "+r.runtimeLeaseCredential,"content-type":"application/json"},body:JSON.stringify({...m,...t})});if(a.assertAttempt(),!i.ok){let t;try{const e=await i.json();f(e)&&f(e.error)&&"string"==typeof e.error.code&&/^[A-Za-z0-9_.:-]{1,128}$/.test(e.error.code)&&(t=e.error.code)}catch(e){if(!(e instanceof SyntaxError))throw new NativeOutputFilesError("native output Files error decode failed")}throw new NativeOutputFilesError("native output Files "+e+" failed ("+i.status+(t?","+t:"")+")")}if(i.url&&new URL(i.url).origin!==d.origin)throw new NativeOutputFilesError("native output Files response origin changed");const s=await i.json();if(a.assertAttempt(),!f(o=s)||o.operationId!==a.operationId||o.requestMessageId!==m.requestMessageId||o.paramsHash!==m.paramsHash||o.activeRunRegistrationId!==m.activeRunRegistrationId)throw new NativeOutputFilesError("native output Files response binding invalid");var o;return s},g=await h("presign",{filename:n,content_type:p,size_bytes:o.byteLength,checksum_sha256:c}),w=g.upload,v=g.transferPolicy;if(!f(w)||!f(v)||"string"!=typeof v.allowedOrigin||"upload"!==w.direction||"PUT"!==w.http_method||"string"!=typeof w.file_id||!w.file_id||"string"!=typeof w.url||"string"!=typeof w.expires_at||!Number.isFinite(Date.parse(w.expires_at))||Date.parse(w.expires_at)<=Date.now()||w.content_type!==p||w.size_bytes!==o.byteLength||w.checksum_sha256!==c||!f(w.required_headers)||Object.values(w.required_headers).some(e=>"string"!=typeof e))throw new NativeOutputFilesError("native output Files transfer descriptor invalid");const y=new URL(w.url),x=new URL(v.allowedOrigin);if("https:"!==y.protocol||y.username||y.password||y.hash||"https:"!==x.protocol||x.username||x.password||"/"!==x.pathname||x.search||x.hash||x.origin!==v.allowedOrigin||y.origin!==x.origin)throw new NativeOutputFilesError("native output Files transfer origin invalid");a.assertAttempt();const b=await fetch(y,{method:"PUT",redirect:"error",signal:u,headers:w.required_headers,body:new Blob([o],{type:p})});if(a.assertAttempt(),!b.ok)throw new NativeOutputFilesError("native output Files PUT failed ("+b.status+")");let _;try{_=await h("confirm",{fileId:w.file_id,checksumSha256:c})}catch(e){if(a.assertAttempt(),u.throwIfAborted(),!(e instanceof TypeError||e instanceof SyntaxError))throw e;_=await h("confirm",{fileId:w.file_id,checksumSha256:c})}if(_.fileId!==w.file_id||_.fileName!==n||_.mimeType!==p||_.size!==o.byteLength)throw new NativeOutputFilesError("native output Files ready metadata mismatch");a.assertAttempt();const I={fileId:w.file_id,uri:"beeos-file://"+w.file_id,name:n,mimeType:p,size:o.byteLength};return noteUploadedDeliverable(e),I}function inferMimeType(e){switch(extname(e).toLowerCase()){case".txt":return"text/plain";case".md":return"text/markdown";case".json":return"application/json";case".html":return"text/html";case".css":return"text/css";case".js":case".mjs":case".cjs":return"text/javascript";case".ts":return"text/x.typescript";case".tsx":case".jsx":return"text/jsx";case".xml":return"application/xml";case".yaml":case".yml":return"application/yaml";case".toml":return"application/toml";case".pdf":return"application/pdf";case".doc":return"application/msword";case".docx":return"application/vnd.openxmlformats-officedocument.wordprocessingml.document";case".xls":return"application/vnd.ms-excel";case".xlsx":return"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";case".ppt":return"application/vnd.ms-powerpoint";case".pptx":return"application/vnd.openxmlformats-officedocument.presentationml.presentation";case".rtf":return"application/rtf";case".odt":return"application/vnd.oasis.opendocument.text";case".ods":return"application/vnd.oasis.opendocument.spreadsheet";case".odp":return"application/vnd.oasis.opendocument.presentation";case".png":return"image/png";case".jpg":case".jpeg":return"image/jpeg";case".gif":return"image/gif";case".webp":return"image/webp";case".svg":return"image/svg+xml";case".mp4":return"video/mp4";case".mov":return"video/quicktime";case".webm":return"video/webm";case".mkv":return"video/x-matroska";case".avi":return"video/x-msvideo";case".m4v":return"video/x-m4v";case".mp3":return"audio/mpeg";case".wav":return"audio/wav";case".flac":return"audio/flac";case".aac":return"audio/aac";case".ogg":return"audio/ogg";case".m4a":return"audio/mp4";case".csv":return"text/csv";case".zip":return"application/zip";case".tar":return"application/x-tar";case".gz":case".tgz":return"application/gzip";default:return"application/octet-stream"}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beeos-claw",
3
- "version": "0.6.63-staging.6",
3
+ "version": "0.6.63-staging.8",
4
4
  "description": "OpenClaw plugin that bridges the BeeOS platform with the local OpenClaw Gateway, providing file transfer, ACP bridge, and observability.",
5
5
  "license": "MIT",
6
6
  "author": "BeeOS <dev@beeos.ai>",
@@ -88,5 +88,5 @@
88
88
  "fast-uri": ">=3.1.4",
89
89
  "brace-expansion": ">=5.0.9"
90
90
  },
91
- "gitHead": "6bf2093ab5b32f062995fc9be8652014af220b36"
91
+ "gitHead": "9fe94a640036329d1487a021169c56a1c22945ca"
92
92
  }