beeos-claw 0.6.63-cloud.0 → 0.6.63-cloud.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/a2a/tools.js +1 -1
- package/dist/acp-gateway/beeos-file-resolver.js +1 -1
- package/dist/acp-gateway/bridge-core.js +1 -1
- package/dist/acp-gateway/gateway-events.js +1 -1
- package/dist/acp-server.js +1 -1
- package/dist/agent-sync.js +1 -1
- package/dist/automation/tools.js +1 -0
- package/dist/automation/turn-policy.js +1 -0
- package/dist/automation/wake.js +1 -0
- package/dist/canvas/relay-client.js +1 -1
- package/dist/canvas/ws-provider.js +1 -1
- package/dist/canvas-orchestrator.js +1 -1
- package/dist/chat-envelope.js +1 -0
- package/dist/connectors/managed-connector-tools.js +1 -0
- package/dist/files/fetch-tool.js +1 -1
- package/dist/files/list-tool.js +1 -1
- package/dist/im-inbound-handler.js +1 -1
- package/dist/im-runtime-dispatch.js +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp-connector-proxy.js +1 -1
- package/dist/media/arouter-config.js +1 -1
- package/dist/media/image-provider.js +1 -1
- package/dist/media/video-provider.js +1 -1
- package/dist/message-client-composition.js +1 -1
- package/dist/runtime/agent-projection-production.js +1 -1
- package/dist/runtime/callback-queue.js +1 -1
- package/dist/runtime/chat-handler-port.js +1 -0
- package/dist/runtime/conversation-title.js +1 -1
- package/dist/runtime/core-execution-attempt-context.js +1 -1
- package/dist/runtime/im-reply-sink.js +1 -1
- package/dist/runtime/message-service-conversation-clear-http-authority.js +1 -1
- package/dist/runtime/message-service-conversation-history-boundary.js +1 -1
- package/dist/runtime/message-service-conversation-run-boundary.js +1 -1
- package/dist/runtime/message-service-cron-delivery-http-authority.js +1 -1
- package/dist/runtime/message-service-runtime-authenticated-fetch.js +1 -1
- package/dist/runtime/message-service-runtime-claim-authority.js +1 -1
- package/dist/runtime/message-service-runtime-message-channel.js +1 -1
- package/dist/runtime/message-service-session-model-http-authority.js +1 -1
- package/dist/runtime/ms-runtime-message-channel-adapter.js +1 -1
- package/dist/runtime/ms-runtime-message-channel-consumer-factory.js +1 -1
- package/dist/runtime/ms-runtime-rpc-adapter.js +1 -1
- package/dist/runtime/native-cloud-chat-composition.js +1 -0
- package/dist/runtime/native-cloud-prompt-bridge.js +1 -0
- package/dist/runtime/native-input-files-http.js +1 -0
- package/dist/runtime/native-input-files.js +1 -0
- package/dist/runtime/native-output-file-attempt.js +1 -0
- package/dist/runtime/native-prompt-authority.js +1 -0
- package/dist/runtime/native-prompt-preflight.js +1 -0
- package/dist/runtime/native-session-new-bridge.js +1 -0
- package/dist/runtime/openclaw-session-model.js +1 -0
- package/dist/runtime/reply-router.js +1 -1
- package/dist/runtime/runtime-error-part.js +1 -0
- package/dist/runtime/runtime-local-parity-matrix.js +1 -1
- package/dist/runtime/runtime-message-channel-contract.js +1 -1
- package/dist/runtime/runtime-operation-resource-resolver.js +1 -1
- package/dist/runtime/runtime-parity-manifest-digest.js +1 -1
- package/dist/runtime/runtime-parity-manifest.js +1 -1
- package/dist/runtime/runtime-production-authority.js +1 -1
- package/dist/runtime/runtime-registration-identity-store.js +1 -1
- package/dist/runtime/runtime-service-contract-compatibility.js +1 -1
- package/dist/runtime/runtime-service-production-candidate.js +1 -1
- package/dist/runtime/runtime-session-control-service.js +1 -1
- package/dist/runtime/runtime-skills-service.js +1 -1
- package/dist/runtime/service-runtime-attempt-ports-resolver.js +1 -1
- package/dist/runtime/session-new-runtime-delivery-bridge.js +1 -1
- package/dist/runtime/write-runtime-failure.js +1 -1
- package/dist/terminal/runtime-terminal-outbound-registration.js +1 -1
- package/dist/terminal/terminal-lease-bound-bridge-client.js +1 -1
- package/dist/upload/desktop-screenshot-tool.js +1 -1
- package/dist/upload/finalize-hook.js +1 -1
- package/dist/upload/tool-artifact-enrichment.js +1 -1
- package/dist/upload/tool.js +1 -1
- package/dist/upload/upload-file.js +1 -1
- package/openclaw.plugin.json +20 -2
- package/package.json +5 -4
- package/runtime-service-wire-identity.v1.json +5 -5
- package/dist/agent-auth.js +0 -1
- package/dist/bridge-discovery.js +0 -1
- package/dist/runtime/agent-gateway-runtime-attempt-authorization.js +0 -1
- package/dist/runtime/message-service-runtime-invocation-authority.js +0 -1
- package/dist/runtime/runtime-jwks-verifier.js +0 -1
- package/dist/runtime/runtime-registration.js +0 -1
- package/dist/runtime/runtime-transport-failure-policy.js +0 -1
- package/dist/runtime/split-runtime-authorization-verifier.js +0 -1
package/dist/files/list-tool.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{CloudHttpError}from"@beeos-ai/cloud-harness-sdk";export const BEEOS_LIST_FILES_TOOL_NAME="beeos_list_files";export const BEEOS_LIST_FILES_TOOL_DESCRIPTION="List files stored in the user's BeeOS account, across all their agents/instances. Use this to discover files the user (or another agent) uploaded or generated earlier, then pass a returned fileId to `beeos_fetch_file` to download it locally. Returns fileId, name, mimeType, size, source and originating instance for each file.";export const BEEOS_LIST_FILES_TOOL_SCHEMA={title:"BeeOS list account files",type:"object",description:BEEOS_LIST_FILES_TOOL_DESCRIPTION,additionalProperties:!1,properties:{query:{type:"string",description:"Optional case-insensitive substring to match against file names."},source:{type:"string",enum:["chat_upload","agent_generated","manual"],description:"Optional filter by file origin."},limit:{type:"integer",minimum:1,maximum:200,description:"Maximum number of files to return (default 50)."}}};const DEFAULT_LIMIT=50,MAX_LIMIT=200,REQUEST_TIMEOUT_MS=3e4;export async function executeListFiles(e,t,r){const i=parseParams(e);if(!i.ok)return errorResult(i.error);if(!t)return errorResult("Agent Gateway client unavailable — listing account files requires agentGatewayUrl and a key pair");const o=AbortSignal.timeout(3e4),s=r?AbortSignal.any([r,o]):o;let n;try{n=await t.files.list({signal:s})}catch(e){return errorResult(e instanceof CloudHttpError?`list ${e.status}: ${e.body}`:`list request failed: ${e instanceof Error?e.message:String(e)}`)}let a=n.files??[];if(i.source&&(a=a.filter(e=>e.source===i.source)),i.query){const e=i.query.toLowerCase();a=a.filter(t=>t.fileName.toLowerCase().includes(e))}a=a.slice(0,i.limit);const l=0===a.length?"No matching files found in the account.":`Found ${a.length} file(s):\n`+a.map(e=>`- ${e.fileName} (${e.mimeType}, ${e.size}B, ${e.source}${e.instanceName?`, from ${e.instanceName}`:""}) → fileId=${e.fileId}`).join("\n"),u={ok:!0,files:a};return{...u,content:[{type:"text",text:l}],output:u,result:u,details:u,isError:!1}}function parseParams(e){const t=e&&"object"==typeof e?e:{},r=new Set(["query","source","limit"]),i=Object.keys(t).filter(e=>!r.has(e));if(i.length>0)return{ok:!1,error:`unexpected properties: ${i.join(", ")}`};let o,s;if(void 0!==t.query){if("string"!=typeof t.query)return{ok:!1,error:"query must be a string"};o=t.query.trim()||void 0}if(void 0!==t.source){if("string"!=typeof t.source)return{ok:!1,error:"source must be a string"};const e=["chat_upload","agent_generated","manual"];if(!e.includes(t.source))return{ok:!1,error:`source must be one of ${e.join(", ")}`};s=t.source}let n=50;if(void 0!==t.limit){if("number"!=typeof t.limit||!Number.isInteger(t.limit)||t.limit<1)return{ok:!1,error:"limit must be a positive integer"};n=Math.min(t.limit,200)}return{ok:!0,query:o,source:s,limit:n}}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{extractChatPrompt}from"
|
|
1
|
+
import{extractChatPrompt}from"./chat-envelope.js";import{buildMentionInstruction,parseMentionsParam}from"./delegation/mention-resolver.js";import{dispatchImInboundPrompt}from"./im-runtime-dispatch.js";import{promptRunKey}from"./runtime/prompt-run-store.js";import{decodeWake}from"./automation/wake.js";const MAX_PROTOCOL_MARKER_LEN=64,DEFAULT_ORIGIN="im",resolveOrigin=e=>"string"!=typeof e||0===e.length||e.length>64?"im":e,conversationIdFromMessage=e=>"string"==typeof e.conversationId?e.conversationId:"";export const createImInboundHandler=e=>{const{runtime:n,pluginConfig:t,client:o,localServer:a,promptRunStore:s,waitIfExclusive:r,assistantMessageCommitRouter:i,toolResultObservationRouter:d,modelCallObservationRouter:c,sessionMutationCoordinator:l,logger:m,writeObs:p,principalIdOverride:g,dispatch:u=dispatchImInboundPrompt,completeA2ATask:I,activeRunAuthority:h,applyTurnModel:v,restoreTurnModel:_}=e;return{onChatMessage:async y=>{const f=decodeWake(y);if("invalid"===f.kind||"wake"===f.kind&&!e.automationTurnPolicy?.isReady())return void m.warn?.("[beeos-claw] Automation Wake rejected: invalid contract or unavailable turn policy");const b=y.content??{},w=b.metadata??void 0,$="string"==typeof w?.target_agent_id?w.target_agent_id:"",R=$?a.resolveLocalAgentId?.($):void 0;if(!$||!R)return void m.warn?.(`[beeos-claw] chat_message target_agent_id=${$||"missing"} not resolvable to a local agent — drop`);const M=extractChatPrompt(y,{source:"chat_message",localAgentId:R});if(!M)return;if(!M.channelId||!M.messageId)return void m.warn?.(`[beeos-claw] chat_message missing channelId/messageId (sessionKey=${M.sessionKey}) — drop`);const O=g||a.getDefaultPlatformAgent()?.instanceId||"";if(!O)return void m.warn?.(`[beeos-claw] chat_message dropped (no principalId resolved, sessionKey=${M.sessionKey})`);const C="string"==typeof w?.delivery_principal?w.delivery_principal:"";if(C&&C!==O)return void m.info?.(`[beeos-claw] chat_message skipped (delivery_principal=${C}, selfPrincipalId=${O}, message_id=${M.messageId})`);const k=parseMentionsParam(b.mentions);a.ensureImInboundSession(M.sessionKey,M.channelId,M.messageId,k);const K=buildMentionInstruction(k),P=K?`${K}\n${M.message}`:M.message,T=resolveOrigin(w?.protocol),A="string"==typeof w?.modelOverrideId&&w.modelOverrideId.length>0?w.modelOverrideId:void 0,j=M.messageId,x="a2a"===T&&I?(e,n)=>I(j,e,n):void 0;m.debug?.(`[beeos-claw] chat_message dispatch (sessionKey=${M.sessionKey}, channelId=${M.channelId}, origin=${T})`);const E=e=>{p({component:"plugin",domain:"im_dispatch",name:`im.dispatch.${e.type}`,severity:"dispatch_error"===e.type?"warn":"info",payload:e})};try{await u({runtime:n,pluginConfig:t,prompt:{channelId:M.channelId,inboundMessageId:M.messageId,requestId:y.requestId,selfPrincipalId:O,dispatchInput:{message:P,attachments:M.files},sessionKey:M.sessionKey,...A?{modelOverrideId:A}:{}},...v?{applyTurnModel:v}:{},..._?{restoreTurnModel:_}:{},client:o,logger:m,promptRunStore:s,...r?{waitIfExclusive:r}:{},assistantMessageCommitRouter:i,toolResultObservationRouter:d,modelCallObservationRouter:c,sessionMutationCoordinator:l,abortTransport:a,origin:T,onLifecycleEvent:E,...x?{onTerminalResult:x}:{},activeRunAuthority:h,..."wake"===f.kind?{enterTurn:(n,t)=>e.automationTurnPolicy.enter(n,t,f.context)}:{}})}catch(e){m.error?.(`[beeos-claw] chat_message dispatch failed channelId=${M.channelId} in_reply_to=${M.messageId} error_code=runtime_dispatch_failed`)}},onChatCancel:async e=>{const n=e.content??{},t="string"==typeof n.target_message_id?n.target_message_id:"",o="string"==typeof n.reason?n.reason:"unknown";if(!t)return void m.warn?.(`[beeos-claw] chat_cancel dropped (no target_message_id, reason=${o})`);const a=conversationIdFromMessage(e);if(!a)return void m.warn?.(`[beeos-claw] chat_cancel dropped (no conversation identity, target_message_id=${t}, reason=${o})`);const r=`chat_cancel:${o}`,i=await s.abort(promptRunKey(a,t),r);i.ok?m.info?.(`[beeos-claw] chat_cancel accepted (target_message_id=${t}, requestId=${i.requestId}, channelId=${i.channelId}, reason=${o})`):m.info?.(`[beeos-claw] chat_cancel no-op (target_message_id=${t}, reason=${o}, why=${i.reason})`)}}};
|
|
@@ -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:s,toolResultObservationRouter:o,modelCallObservationRouter:c,sessionMutationCoordinator:d,abortTransport:l,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=randomUUID(),I=Date.now();logChatLatency(a,"claw.inbound.received",m,I,{origin:e.origin??"im",request_id_source:t.requestId?"realtime_correlation":"message_id_fallback"});const g=e.origin??"im",h={protocol:"im",requestId:m,sessionId:t.sessionKey??"agent:main",sourceMessageId:t.inboundMessageId,chatId:t.channelId,origin:g},y=async(n,r)=>{if(e.onTerminalResult)try{await e.onTerminalResult(n,r)}catch(e){a.warn?.(`[im] terminal business callback failed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}},_=promptRunKey(t.channelId,t.inboundMessageId),R=t.sessionKey??"agent:main",f=new AbortController;let b,E,w;const M=new Promise((e,n)=>{w=n});let $;const S=()=>{void 0!==$&&(clearTimeout($),$=void 0)};if(e.waitIfExclusive)try{await e.waitIfExclusive("im_dispatch",f.signal)}catch(n){return a.warn?.(`[im] runtime dispatch aborted waiting for exclusive mutation requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:n instanceof Error?n.message:String(n),cause:"abort"}),!1}if(!i.register(_,{requestId:m,channelId:t.channelId,requestCancel:async e=>{if(E??=e,f.abort(e),!b)return{ok:!0};const n=await d.requestCancel(b,l);return n.ok?n.terminalObservation.then(e=>{e.ok||w(new Error(SESSION_RECOVERY_REQUIRED_CODE))}):w(new Error(SESSION_RECOVERY_REQUIRED_CODE)),{ok:n.ok}},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 v=deterministicReplyMessageId("asst",t.channelId,t.inboundMessageId,t.selfPrincipalId),C={conversationId:t.channelId,clientMessageId:v,idempotencyKey:v,replyTo:e.inReplyTo??t.inboundMessageId,requestId:m,type:"agent_reply",content:{}},q=r.messages.startStream(C);let k,O=!1;try{const e=await q.opened();O="duplicate"===e.outcome,logChatLatency(a,"claw.reply_stream.opened",m,I,{outcome:e.outcome})}catch(n){let s="unconfirmed";try{s=(await r.messages.getEnvelope(t.channelId,v)).state}catch{}return a.warn?.(`[im] runtime reply stream open outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} reply_id=${v} reconciled_state=${s}: ${formatErrMessage(n)}; runtime_not_invoked`),e.onLifecycleEvent?.({type:"skipped",reason:"reply_open_outcome_unknown",channelId:t.channelId,inboundMessageId:t.inboundMessageId}),i.unregister(_),!1}if(O)return a.info?.(`[im] runtime dispatch skipped existing deterministic reply requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}`),e.onLifecycleEvent?.({type:"skipped",reason:"idempotent_reply_exists",channelId:t.channelId,inboundMessageId:t.inboundMessageId}),i.unregister(_),!1;const L=new SerializedCallbackQueue,A=createImReplySink({stream:q,abortSignal:f.signal,callbackQueue:L,logger:a,requestId:m,startedAtMs:I,runId:p,channelId:t.channelId,inboundMessageId:t.inboundMessageId,origin:g,sessionKey:R,onAgentRunStart:e=>{d.bindRun(b,e),void 0!==k&&logChatLatency(a,"claw.runtime.pre_run_completed",m,k)}}),T=interceptAgentRuntimeFailures(A,"im_runtime",e=>a.warn?.(`[im] runtime failure reply suppressed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} error_code=${e.errorCode}`)),D=T.sink;let F=!1;const U=async e=>{D.dispatcher.markComplete(e);try{await D.dispatcher.waitForIdle()}catch{}},K=()=>{S();const n=normalizePositiveTimeoutMs(e.abortTerminalGraceMs)??1e4;$=setTimeout(()=>{$=void 0,(async()=>{if(q.isTerminated)return;const e=f.signal.reason??E,n="string"==typeof e&&e.startsWith("chat_cancel");if(await U("failure"),!q.isTerminated)try{n?await q.cancel({stopReason:"user_stop"}):await failMessageStream(q,{body:SESSION_RECOVERY_REQUIRED_MESSAGE,stopReason:"error"}),a.warn?.(`[im] abort settlement watchdog terminalized reply requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} user_cancel=${n}`)}catch(e){a.warn?.(`[im] abort settlement watchdog terminal write failed requestId=${m} channel=${t.channelId}: ${formatErrMessage(e)}`)}})()},n)};f.signal.aborted?K():f.signal.addEventListener("abort",K,{once:!0});const N=()=>{if(!f.signal.aborted)return;const e=f.signal.reason;throw e instanceof Error?e:new Error(String(e??"runtime dispatch aborted"))};let P,G,Q,j,Y,x;const B=async e=>{if(!b)throw new Error("session_mutation_not_acquired");const n=await d.converge(b,e);return n.ok?(P=n.permit,!0):(a.error?.(`[im] session mutation recovery required requestId=${m} sessionKey=${R} reason=${n.recovery.reason}`),G={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{N();const l=d.tryStartInteractive({sessionKey:R,label:"im_chat_message"},"message_service");if(!l.ok){try{await failMessageStream(q,{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=${l.activeOperationId??"unknown"}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:"session_busy",cause:"runtime_error"}),!1}if(b=l.token,logChatLatency(a,"claw.session_gate.acquired",m,I),d.bindRun(b,p),j=s.register(R,A),Y=o.register(R,A),x=c.register(p,{requestId:m,startedAtMs:I,logger:a}),u){const e=d.snapshot(R);Q={runtimeConversationUid:t.channelId,runtimeSessionKey:t.channelId,historyGeneration:u.historyGeneration(t.channelId),targetMessageId:t.inboundMessageId,runtimeRunId:p,activeRunRegistrationId:`im:${e?.operationId??p}`},u.activeRuns.register(Q,async()=>{const e=`chat_cancel:activeRun:${Q.activeRunRegistrationId}`,n=await i.abort(_,e);return n.ok||"already_aborted"===n.reason?"accepted":"terminal_committing"===n.reason||"not_found"===n.reason?"already_terminal":"recovery_required"})}N(),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}),k=Date.now(),logChatLatency(a,"claw.runtime.invoke",m,I);const f=setTimeout(()=>{const e=Date.now()-k-100;e>=500&&logChatLatency(a,"claw.runtime.event_loop_lag",m,k,{lag_ms:e,phase:"pre_run"})},100);f.unref?.();const E=dispatchRuntimeReplyWithRoute({runtime:n,pluginConfig:e.pluginConfig,preparedPrompt:t.dispatchInput,replyRoute:h,replySinks:{im:D},onDispatchInvoked:()=>{F=!0,logChatLatency(a,"claw.runtime.dispatch_returned",m,k)}}),w=await Promise.race([E,M]).finally(()=>{}),$=T.detectedFailure();if($)throw new Error($.diagnosticMessage);if(N(),await U("success"),N(),!i.claimTerminal(_,"completion")){if(N(),"cancelling"===i.phase(_))throw new Error("cancellation in progress");throw new Error("terminal outcome already claimed")}if(!await B("completed"))return await failMessageStream(q,{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",...G?{recovery:G}:{}}),!1;const S=D.dispatcher.getTerminalErrorText?.();if(void 0!==S){let n=!1;const r=classifyAgentRuntimeFailure({raw:S,source:"im_runtime",runtimeKind:"openclaw"});try{await writeRuntimeFailure(q,{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&&Q&&u.activeRuns.markTerminal(Q,"failed"),a.warn?.(`[im] runtime dispatch ended with an error terminal requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} counts=${JSON.stringify(w.counts)} terminalWriteFailed=${n} elapsed_ms=${Date.now()-I}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:"runtime_error_terminal_reply",cause:"runtime_error"}),n||await y("",S),!1}let v=!1;try{await q.finalize({stopReason:"end_turn"})}catch(e){v=!0,a.warn?.(`[im] runtime reply stream finalize outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}u&&Q&&u.activeRuns.markTerminal(Q,"completed");const C={...w.counts,source:A.getSourceCount()};a.info?.(`[im] runtime dispatch completed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} counts=${JSON.stringify(C)} elapsed_ms=${Date.now()-I}`),logChatLatency(a,"claw.turn.terminal",m,I,{outcome:v?"outcome_unknown":"completed",tool_count:C.tool}),e.onLifecycleEvent?.({type:"dispatch_complete",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,counts:C,...v?{terminalWriteFailed:!0}:{}});const O=D.dispatcher.getAccumulatedBody?.()??"";v||await y(O,"");const L="string"==typeof t.dispatchInput.message?t.dispatchInput.message:"";return maybeRenameImConversationTitle({client:r,conversationId:t.channelId,question:L,answer:O,logger:a}),!0}catch(n){await U("failure");const r=f.signal.aborted,s=r?f.signal.reason:void 0,o="cancelling"===i.phase(_),c=s??E,d="string"==typeof c&&c.startsWith("chat_cancel");let l="runtime_error";(r||o)&&(l="abort");const p=o||d||r?"cancellation":"completion";if(!i.claimTerminal(_,p)){if(a.warn?.(`[im] terminal claim raced requestId=${m} channel=${t.channelId}; best-effort envelope terminal if still streaming`),!q.isTerminated)try{d?await q.cancel({stopReason:"user_stop"}):await failMessageStream(q,{body:formatErrMessage(n),stopReason:"error"})}catch(e){a.warn?.(`[im] raced terminal write failed requestId=${m}: ${formatErrMessage(e)}`)}throw n}const g=d?"cancelled":"error";if(u&&Q&&u.activeRuns.markTerminal(Q,"cancelled"===g?"cancelled":"failed"),b&&!await B(g))throw d?await q.cancel({stopReason:"user_stop"}).catch(()=>{}):await failMessageStream(q,{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:l,...G?{recovery:G}:{}}),n;const h=classifyAgentRuntimeFailure({raw:n,source:"im_runtime",runtimeKind:"openclaw",requestAborted:d}),R=d?h:T.detectedFailure()??h;let w=!1;try{d?await q.cancel({stopReason:"user_stop"}):await writeRuntimeFailure(q,{body:R.publicMessage,stopReason:messageStopReasonForRuntimeFailure(R),businessErrorCode:R.businessErrorCode})}catch(e){w=!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=${l} dispatchInvoked=${F} error_code=${R.errorCode}`),logChatLatency(a,"claw.turn.terminal",m,I,{outcome:l,error_code:R.errorCode}),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:R.errorCode,cause:l}),d||w||await y("",R.publicMessage),n}finally{S(),x?.(),Y?.(),j?.(),i.unregister(_),F?P&&d.release(P):d.releaseBeforeRuntime(b)}};
|
|
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},y=async(n,r)=>{if(e.onTerminalResult)try{await e.onTerminalResult(n,r)}catch(e){a.warn?.(`[im] terminal business callback failed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}},_=promptRunKey(t.channelId,t.inboundMessageId),R=t.sessionKey??"agent:main",f=new AbortController;let w,E,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 k;const O=()=>{void 0!==k&&(clearTimeout(k),k=void 0)},T=async e=>{if($??=e,f.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",f.signal)}catch(n){return a.warn?.(`[im] runtime dispatch aborted waiting for exclusive mutation requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:n instanceof Error?n.message:String(n),cause:"abort"}),!1}if(!i.register(_,{requestId:m,channelId:t.channelId,requestCancel:T,startedAt:I,sessionKey:R}))return a.warn?.(`[im] runtime dispatch rejected duplicate inboundMessageId=${t.inboundMessageId} requestId=${m} channel=${t.channelId}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:"duplicate_inbound_message_id",cause:"abort"}),!1;const L=e.retainedStream?.id??deterministicReplyMessageId("asst",t.channelId,t.inboundMessageId,t.selfPrincipalId),A={conversationId:t.channelId,clientMessageId:L,idempotencyKey:L,replyTo:e.inReplyTo??t.inboundMessageId,requestId:m,type:"agent_reply",content:{}},D=e.retainedStream??r.messages.startStream(A);let F,U=!1;try{const e=await D.opened();U="duplicate"===e.outcome,logChatLatency(a,"claw.reply_stream.opened",m,I,{outcome:e.outcome})}catch(n){let o="unconfirmed";try{o=(await r.messages.getEnvelope(t.channelId,L)).state}catch{}return a.warn?.(`[im] runtime reply stream open outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} reply_id=${L} reconciled_state=${o}: ${formatErrMessage(n)}; runtime_not_invoked`),e.onLifecycleEvent?.({type:"skipped",reason:"reply_open_outcome_unknown",channelId:t.channelId,inboundMessageId:t.inboundMessageId}),i.unregister(_),!1}if(U)return a.info?.(`[im] runtime dispatch skipped existing deterministic reply requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}`),e.onLifecycleEvent?.({type:"skipped",reason:"idempotent_reply_exists",channelId:t.channelId,inboundMessageId:t.inboundMessageId}),i.unregister(_),!1;const K=()=>{T(e.abortSignal?.reason).catch(e=>{C(e instanceof Error?e:new Error(String(e)))})};e.abortSignal?.addEventListener("abort",K,{once:!0}),e.abortSignal?.aborted&&K();const P=new SerializedCallbackQueue,Q=createImReplySink({stream:D,persistObservedToolResults:void 0!==e.retainedStream,abortSignal:f.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!==F&&logChatLatency(a,"claw.runtime.pre_run_completed",m,F)}}),G=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}`)),Y=G.sink;let j=!1,x=!1;const V=async n=>{e.onNativeRunCompletion||Y.dispatcher.markComplete(n);try{e.onNativeRunCompletion&&Y.dispatcher.markComplete(n),await Y.dispatcher.waitForIdle()}catch(n){if(e.onNativeRunCompletion)throw P.fail(n),n}},B=()=>{if(e.onNativeRunCompletion)return;O();const n=normalizePositiveTimeoutMs(e.abortTerminalGraceMs)??1e4;k=setTimeout(()=>{k=void 0,(async()=>{if(D.isTerminated)return;const e=f.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)};f.signal.aborted?B():f.signal.addEventListener("abort",B,{once:!0});const z=()=>{if(!f.signal.aborted)return;const e=f.signal.reason;throw e instanceof Error?e:new Error(String(e??"runtime dispatch aborted"))};let W,J,H,X,Z,ee,ne;const te=async e=>{if(!w)throw new Error("session_mutation_not_acquired");const n=await l.converge(w,e);return n.ok?(W=n.permit,!0):(a.error?.(`[im] session mutation recovery required requestId=${m} sessionKey=${R} reason=${n.recovery.reason}`),J={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(z(),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),X=o.register(R,Q),Z=s.register(R,Q),ee=c.register(p,{requestId:m,startedAtMs:I,logger:a}),u){const n=l.snapshot(R);H=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(H,async()=>{const e=`chat_cancel:activeRun:${H.activeRunRegistrationId}`,n=await i.abort(_,e);return n.ok||"already_aborted"===n.reason?"accepted":"terminal_committing"===n.reason||"not_found"===n.reason?"already_terminal":"recovery_required"})}z(),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(),z()),e.onNativeRunCompletion&&e.prepareNativeModel&&(await e.prepareNativeModel(w),z(),await(e.assertNativeTarget?.()),z());const f=t.modelOverrideId;"string"==typeof f&&f.length>0&&R.length>0&&e.applyTurnModel&&(await e.applyTurnModel(R,f),x=!0,z()),F=Date.now(),ne=e.enterTurn?.(R,p),logChatLatency(a,"claw.runtime.invoke",m,I);const S=setTimeout(()=>{const e=Date.now()-F-100;e>=500&&logChatLatency(a,"claw.runtime.event_loop_lag",m,F,{lag_ms:e,phase:"pre_run"})},100);S.unref?.();const $=()=>dispatchRuntimeReplyWithRoute({runtime:n,pluginConfig:e.pluginConfig,preparedPrompt:t.dispatchInput,replyRoute:h,replySinks:{im:Y},onDispatchInvoked:n=>{if(j=!0,e.onNativeRunCompletion){E=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,F)}}),C=ne?ne.run($):$(),N=e.onNativeRunCompletion?await C:await Promise.race([C,q]).finally(()=>{});e.onNativeRunCompletion&&(await E,await b);const k=G.detectedFailure();if(k)throw new Error(k.diagnosticMessage);if(z(),await V("success"),e.onNativeRunCompletion&&await b,z(),!i.claimTerminal(_,"completion")){if(z(),"cancelling"===i.phase(_))throw new Error("cancellation in progress");throw new Error("terminal outcome already claimed")}if(!await te("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",...J?{recovery:J}:{}}),!1;const O=Y.dispatcher.getTerminalErrorText?.();if(void 0!==O){let n=!1;const r=classifyAgentRuntimeFailure({raw:O,source:"im_runtime",runtimeKind:"openclaw"});try{await writeRuntimeFailure(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&&H&&u.activeRuns.markTerminal(H,"failed"),a.warn?.(`[im] runtime dispatch ended with an error terminal requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} counts=${JSON.stringify(N.counts)} terminalWriteFailed=${n} elapsed_ms=${Date.now()-I}`),e.onLifecycleEvent?.({type:"dispatch_error",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,error:"runtime_error_terminal_reply",cause:"runtime_error"}),n||await y("",O),!1}let T=!1;try{await D.finalize({stopReason:"end_turn"})}catch(e){T=!0,a.warn?.(`[im] runtime reply stream finalize outcome unknown requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId}: ${formatErrMessage(e)}`)}u&&H&&u.activeRuns.markTerminal(H,"completed");const L={...N.counts,source:Q.getSourceCount()};a.info?.(`[im] runtime dispatch completed requestId=${m} channel=${t.channelId} in_reply_to=${t.inboundMessageId} counts=${JSON.stringify(L)} elapsed_ms=${Date.now()-I}`),logChatLatency(a,"claw.turn.terminal",m,I,{outcome:T?"outcome_unknown":"completed",tool_count:L.tool}),e.onLifecycleEvent?.({type:"dispatch_complete",requestId:m,channelId:t.channelId,inboundMessageId:t.inboundMessageId,counts:L,...T?{terminalWriteFailed:!0}:{}});const A=Y.dispatcher.getAccumulatedBody?.()??"";T||await y(A,"");const U="string"==typeof t.dispatchInput.message?t.dispatchInput.message:"";return maybeRenameImConversationTitle({client:r,conversationId:t.channelId,question:U,answer:A,logger:a}),!0}catch(n){S=n,e.onNativeRunCompletion&&(await(E?.then(()=>{},()=>{})),await b),await V("failure"),e.onNativeRunCompletion&&await b;const r=f.signal.aborted,o=r?f.signal.reason:void 0,s="cancelling"===i.phase(_),c=o??$,l="string"==typeof c&&c.startsWith("chat_cancel");let d="runtime_error";(r||s)&&(d="abort");const p=s||l||r?"cancellation":"completion";if(!i.claimTerminal(_,p)){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&&H&&!e.onNativeRunCompletion&&u.activeRuns.markTerminal(H,"cancelled"===g?"cancelled":"failed"),w&&!await te(g))throw u&&H&&e.onNativeRunCompletion&&u.activeRuns.markTerminal(H,"cancelled"===g?"cancelled":"failed"),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,...J?{recovery:J}:{}}),n;u&&H&&e.onNativeRunCompletion&&u.activeRuns.markTerminal(H,"cancelled"===g?"cancelled":"failed");const h=classifyAgentRuntimeFailure({raw:n,source:"im_runtime",runtimeKind:"openclaw",requestAborted:l}),R=l?h:G.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 y("",R.publicMessage),n}finally{if(e.onNativeRunCompletion&&(W?v?.(W):(j&&w&&l.requireRecovery(w,"terminal_not_observed"),M?.(S??new Error(SESSION_RECOVERY_REQUIRED_CODE)))),e.abortSignal?.removeEventListener("abort",K),j&&!W||ne?.close(),O(),ee?.(),Z?.(),X?.(),i.unregister(_),x&&e.restoreTurnModel&&R)try{await e.restoreTurnModel(R)}catch(e){a.error?.(`[im] turn model restore failed requestId=${m} sessionKey=${R}: ${formatErrMessage(e)}`)}j?W&&l.release(W):l.releaseBeforeRuntime(w)}};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
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{createTokenProvider}from"@beeos-ai/message-sdk/auth";import{BeeosClawMessageClientProcessOwner}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{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,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 r=>{const{createPrivateKey:t,sign:o}=await import("node:crypto"),n=t({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(r),n))}}}let sharedPluginContext=null,unhandledRejectionObserverInstalled=!1;function installUnhandledRejectionObserver(e,r,t){unhandledRejectionObserverInstalled||(unhandledRejectionObserverInstalled=!0,process.on("unhandledRejection",t=>{const o=t instanceof Error?t.message:String(t),n=t instanceof Error?t.stack:void 0;e.logger.error?.(`[beeos-claw] unhandledRejection: ${o}${n?`\n${n}`:""}`),r({component:"plugin",domain:"fatal",name:"unhandled_rejection",severity:"error",summary:o,error:{code:"unhandled_rejection",message:o,...n?{stack:n}:{}}})}),process.on("uncaughtException",t=>{const o=t instanceof Error?t.message:String(t);e.logger.error?.(`[beeos-claw] uncaughtException: ${t instanceof Error?t.stack??t.message:String(t)}`),r({component:"plugin",domain:"fatal",name:"uncaught_exception",severity:"error",summary:o,error:{code:"uncaught_exception",message:o}})}))}function initializePlugin(e){let r,t;try{r=e.runtime?.config?.loadConfig?.()}catch{}try{t=resolveConfigWithMeta({pluginConfig:e.pluginConfig??{},openclawConfig:r})}catch(r){return e.logger.error?.(`[beeos-claw] Failed to resolve config: ${r instanceof Error?r.message:String(r)}`),null}const o=t.config,n=buildThirdPartyChannelSet(r);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:t.sources,openclawConfigPath:t.openclawConfigPath}});for(const r of t.validation)a({component:"plugin",domain:"config",name:"config.validation",severity:r.severity,summary:r.message,error:{code:r.code,message:r.message,nextSteps:r.nextSteps}}),"error"===r.severity?e.logger.error?.(`[beeos-claw] ${r.message}`):e.logger.warn?.(`[beeos-claw] ${r.message}`);if(t.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 r=Buffer.from(agentKeys.publicKey).toString("base64");e.logger.info?.(`[beeos-claw] v${PLUGIN_VERSION} registering (publicKey: ${r})`)}catch(r){e.logger.warn?.(`[beeos-claw] Failed to load agent key pair: ${r}`),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=r,{cfg:o,writeObs:a,thirdPartyChannels:n,openclawConfig:r}}function registerUploadTools(e,r,t){const{cfg:o,writeObs:n}=r;cleanupUploadToolResultCache().catch(r=>{e.logger.warn?.(`[beeos_upload_file] cache cleanup failed on startup: ${String(r)}`)}),e.registerTool({name:BEEOS_UPLOAD_TOOL_NAME,description:BEEOS_UPLOAD_TOOL_DESCRIPTION,parameters:BEEOS_UPLOAD_TOOL_SCHEMA,async execute(r,t,a){e.logger.debug?.(`[beeos_upload_file] toolCallId=${r} params=${JSON.stringify(t)}`);const i=await executeUpload(t,o,agentKeys,a);return e.logger.debug?.(`[beeos_upload_file] toolCallId=${r} ok=${i.ok}`),n({component:"upload-tool",domain:"tool",name:i.ok?"upload.success":"upload.failure",severity:i.ok?"info":"warn",payload:{toolCallId:r,ok:i.ok,fileCount:i.files?.length??0,error:i.error}}),(async t=>{try{await writeUploadToolResult(r,BEEOS_UPLOAD_TOOL_NAME,t),await cleanupUploadToolResultCache()}catch(t){e.logger.warn?.(`[beeos_upload_file] persist cache failed toolCallId=${r}: ${String(t)}`)}return t})(i)}}),e.registerTool({name:BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,description:BEEOS_DESKTOP_SCREENSHOT_TOOL_DESCRIPTION,parameters:BEEOS_DESKTOP_SCREENSHOT_TOOL_SCHEMA,async execute(r,t,a){e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${r} params=${JSON.stringify(t)}`);const i=await executeDesktopScreenshot(t,o,agentKeys,a);return e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${r} 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:r,ok:i.ok,path:i.path,fileCount:i.files?.length??0,error:i.error}}),(async t=>{try{await writeUploadToolResult(r,BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,t),await cleanupUploadToolResultCache()}catch(t){e.logger.warn?.(`[beeos_desktop_screenshot] persist cache failed toolCallId=${r}: ${String(t)}`)}return t})(i)}}),e.registerHttpRoute({path:"/beeos/files/stage",auth:"gateway",async handler(e,t){await handleFileStage(e,t,r.cfg)}}),e.registerHttpRoute({path:"/beeos/status",auth:"plugin",handler(e,r){handleStatusRequest(e,r,{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(r,t,a){e.logger.debug?.(`[beeos_list_files] toolCallId=${r} params=${JSON.stringify(t)}`);const i=await executeListFiles(t,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:r,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(r,t,a){e.logger.debug?.(`[beeos_fetch_file] toolCallId=${r} params=${JSON.stringify(t)}`);const i=await executeFetchFile(t,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:r,ok:i.ok,path:i.path,size:i.size,error:i.error}}),i}})}function registerConnectorMcpProxy(e,r){e.registerHttpRoute({path:CONNECTOR_MCP_PROXY_PATH,auth:"plugin",async handler(t,o){await handleConnectorMcpRequest(t,o,{agentGatewayUrl:r.cfg.agentGatewayUrl,agentKeys:agentKeys,logger:e.logger})}})}function registerServices(e,r,t){const{cfg:o,writeObs:n,thirdPartyChannels:a}=r;if("function"!=typeof e.on){if(o.messageBus.enabled)throw new Error("openclaw_before_message_write_hook_unavailable")}else registerModelCallObservationHooks((r,t)=>e.on(r,t),sharedModelCallObservationRouter),e.on("before_message_write",(r,t)=>{const o=r.sessionKey??t.sessionKey;if(!o)return void e.logger.debug?.("[before_message_write] ignored assistant write without sessionKey");sharedAssistantMessageCommitRouter.route(o,r.message)||e.logger.debug?.(`[before_message_write] no active IM commit target sessionKey=${o} active_targets=${sharedAssistantMessageCommitRouter.size()}`)}),e.on("after_tool_call",(r,t)=>{const o=t.sessionKey,n=r.toolCallId??t.toolCallId,a=r.toolName||t.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(r,o);sharedToolResultObservationRouter.route(o,{toolCallId:n,toolName:a,rawResult:r.result,isError:Boolean(r.error)})||e.logger.debug?.(`[after_tool_call] no active IM observation target sessionKey=${o} active_targets=${sharedToolResultObservationRouter.size()}`)});const i=agentKeys?(e,r)=>agentFetch(e,agentKeys,r):void 0,s=agentKeys?(e,r)=>agentBoundFetch(e,agentKeys,r):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 d=cloudRuntimeTargetInstanceId(process.env);if(d&&(!agentKeys||!o.agentGatewayUrl||!i||!s))throw new Error("Cloud runtime authority requires an agent identity and gateway transport");if(sharedRuntimeAuthority&&sharedRuntimeAuthority.cloudTargetInstanceId!==d)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:d,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 r=sharedRuntimeAuthority;sharedAgentProjection=new AgentProjectionProduction({authority:r,stateFile:join(r.stateDirectory,"runtime-agent-projection.json"),journal:r.journal,identities:r.identities,source:new OpenClawAgentProjectionSource(()=>sharedGatewayClient),transport:new AgentGatewayHttpProjectionTransport({agentGatewayUrl:o.agentGatewayUrl,boundAgentFetch:r.boundAgentFetch,getRuntimeLeaseCredential:e=>{const t=r.authorityLease;if(!t||t.instanceId!==e.instanceId||t.leaseId!==e.leaseId||t.runtimeEpoch!==e.runtimeEpoch||t.handlerIdentity!==e.handlerIdentity)throw new Error("agent projection fenced by current runtime lease");return t.runtimeLeaseCredential},onAccepted:r=>{0!==r.size&&sharedAgentMappings.replace(r).catch(r=>{e.logger.warn?.("[agent-projection] mapping publication failed: "+(r instanceof Error?r.message:String(r)))})}}),capabilities:sharedRuntimeAgentCapabilities,logger:e.logger})}sharedRuntimeOwner??=new OpenClawRuntimeProcessOwner(sharedGatewayClient,sharedAgentProjection,e.logger);const u=sharedRuntimeOwner;sharedSessionMutationCoordinator??=new SessionMutationCoordinator(sharedSessionWriteGate,new OpenClawSessionWriteQuiescence(e.logger,{agentId:o.gateway.agentId||"main"}),e.logger,{onRecoveryRequired:r=>{scheduleProcessRuntimeRestart(r,e.logger)}});const m=sharedSessionMutationCoordinator;if(!sharedAcpServer){const r=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:u.client,agentProjection:sharedAgentProjection,markAgentProjectionDirty:()=>sharedAgentProjection?.markDirty(),templateOriginReporter:r,agentMappings:sharedAgentMappings,agentCapabilities:sharedRuntimeAgentCapabilities,createRunOutputRouter:createPeerRunOutputRouterFactory(new MessageServiceRunOutputChannel({getClient:()=>sharedMessageClientOwner.current?.client??null,logger:e.logger,writeObs:n})),runExclusive:(r,t,o)=>sharedImHotPathDeferral.runExclusive(r,t,e.logger,o)})}const p=sharedAcpServer,y=()=>sharedAgentMappings.snapshot()?.values().next().value;t.current=p,sharedMcpNativeProjectionNudge.request({registrationMode:e.registrationMode,fingerprint:fingerprintMcpServers(r.openclawConfig),logger:e.logger});const h=sharedPromptRunStore,{enabled:f,principalId:w,a2aEnabled:R}=o.messageBus;let v;o.agentGatewayUrl&&agentKeys&&(v=createTokenProvider({agentGatewayUrl:o.agentGatewayUrl,identity:agentKeyPairToIdentity(agentKeys)}));const C=process.env.MESSAGE_RUNTIME_DELIVERY_KEY?.trim(),b=w||process.env.BEEOS_PRINCIPAL_ID||"",_=v?sharedMessageClientOwner.configure({tokenProvider:v,identityId:b,...o.messageBus.serviceUrl?{serviceUrl:o.messageBus.serviceUrl}:{},logger:e.logger,...sharedRuntimeAuthority&&C?{runtimeDelivery:{scopedDeliveryKey:C,authority:{currentLease:()=>{const e=sharedRuntimeAuthority?.authorityLease,r=sharedRuntimeAuthority?.currentConsumerBinding();return e&&r?{...e,journalStoreId:r.journalStoreId,journalGeneration:r.journalGeneration}:null}}}}:{}}):void 0,S=sharedRuntimeAuthority,E=o.messageBus.serviceUrl;if(_&&S&&E&&C){const e=_.nodeTransport;p.setCronConversationDelivery({deliver:async r=>{const t=S.authorityLease;if(!t)throw new Error("current runtime authority lease unavailable for cron delivery");const o=new MessageServiceCronDeliveryHttpAuthority({messageServiceUrl:E,fetchAuthorized:async(r,o)=>await e.fetchRuntimeChannel(r,{runtimeLeaseCredential:t.runtimeLeaseCredential},o)});return await o.deliver({...r,runtimeLeaseCredential:t.runtimeLeaseCredential})}})}else p.setCronConversationDelivery(void 0);const O=sharedRuntimeAuthority?.journal??new FileRuntimeCommandJournal(join(c,"runtime-command-journal.json"),void 0,void 0,{onMaintenanceError:r=>e.logger.error?.(`[runtime-journal] event=checkpoint_failed trigger=threshold error=${r instanceof Error?r.message:String(r)}`)}),A=u.createRegistrationToken();e.registerService({id:"beeos-acp",async start(){const r=Date.now(),t=_pluginRegisteredAt?r-_pluginRegisteredAt:-1;e.logger.info?.(`[beeos-claw] beeos-acp service start() begin, sincePluginRegister=${t}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})}:{},commandJournal:O,poisonJournal:new FileRuntimePoisonDeliveryJournal(join(c,"runtime-poison-deliveries.json")),onConsumerDeliveryError:r=>{const t=r instanceof Error?`${r.name}: ${r.message}${"status"in r?` status=${r.status}`:""}${"code"in r?` code=${r.code}`:""}\n${r.stack??""}`:String(r);e.logger.error?.(`[runtime-service] delivery worker failed before acknowledgement; delivery retained for retry: ${t}`)},onConsumerLeaseStarvation:({starvedForMs:r,recovered:t})=>{const o=Math.round(r/1e3);t?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:r=>e.logger.error?.(`[runtime-service] request failed operationId=${r.operationId} method=${r.method}: ${r.error instanceof Error?r.error.stack??r.error.message:String(r.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 r=Date.now(),t=await discoverBridgeFromGW(o.agentGatewayUrl,i);if(e.logger.info?.(`[beeos-claw] bridge discovery took ${Date.now()-r}ms result=${t?.url??"null"}`),t)o.bridge.url=t.url,writeDiscoveryCache({bridge:{url:t.url,discoveredAt:Date.now()}}),e.logger.info?.(`[beeos-claw] Bridge URL discovered from Agent Gateway: ${t.url}`);else{const r=readDiscoveryCache();r?.bridge?.url?(o.bridge.url=r.bridge.url,e.logger.info?.(`[beeos-claw] Bridge URL from cache (GW unreachable): ${r.bridge.url}`)):e.logger.debug?.("[beeos-claw] Bridge URL not available (no GW, no cache) — bridge disabled")}}await u.acquire(A);try{await p.start(o.bridge.url||void 0)}catch(e){throw await u.release(A),e}e.logger.info?.(`[beeos-claw] ACP Server started (total service start: ${Date.now()-r}ms)`)},async stop(){try{await u.release(A)}finally{await p.stop()}await O.checkpoint(),e.logger.info?.("[runtime-service] command journal checkpoint completed"),e.logger.info?.("[beeos-claw] ACP Server stopped")}});if(f&&void 0!==v&&v){const r=sharedMessageClientOwner.createRegistrationToken(),t=async(e,r)=>{const t=await v(e);if(!t.identityId||t.identityId!==e)throw new Error("Message SDK token identity did not match the current runtime authority");return{principalId:e,runtimeEpoch:r}},a=(e,r,t)=>({getLocalAgentId:()=>r,resolveLocalAgentId:e=>e===t?r:void 0,getDefaultPlatformAgent:()=>({instanceId:e.principalId}),ensureImInboundSession:(e,r,t,o)=>{p.ensureImInboundSession(e,r,t,o)},chatAbort:(e,r)=>p.chatAbort(e,r)}),i=sharedRuntimeAuthority?new RuntimeAuthorityMessageBusLifecycle({authority:sharedRuntimeAuthority,logger:e.logger,bus:{connect:async i=>{await sharedMessageClientOwner.acquire(r,async r=>{const s=await t(i.instanceId,i.runtimeEpoch),l=r.client,c={leaseId:i.leaseId,runtimeEpoch:i.runtimeEpoch};sharedMSConnectionStatus.bind(c);const d=new Map,u=new MessageProjectionInboundConsumer({client:l,bindings:()=>{const r=sharedRuntimeAuthority?.authorityLease;if(!r||r.instanceId!==s.principalId||r.runtimeEpoch!==s.runtimeEpoch)return[];const t=sharedAgentMappings.snapshot();return t?[...t.entries()].flatMap(([t,i])=>{if(!i.id||i.instanceId!==s.principalId)return[];let c=d.get(i.id);return c&&c.localAgentId===t||(c={localAgentId:t,inbound:createImInboundHandler({runtime:e.runtime,pluginConfig:e.pluginConfig,client:l,localServer:a(s,t,i.id),promptRunStore:h,waitIfExclusive:(r,t)=>sharedImHotPathDeferral.waitIfExclusive(r,e.logger,t).then(()=>{}),assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:m,logger:e.logger,writeObs:n,principalIdOverride:s.principalId,activeRunAuthority:p.getActiveRunAuthority(),...o.agentGatewayUrl&&agentKeys?{completeA2ATask:(r,t,n)=>completeA2ATask({agentGatewayUrl:o.agentGatewayUrl,agentKeys:agentKeys,logger:e.logger},r,t,n)}:{}})},d.set(i.id,c)),[{principalId:s.principalId,targetAgentId:i.id,runtimeEpoch:r.runtimeEpoch,inbound:c.inbound}]}):[]},executionJournal:g,logger:e.logger}),y=sharedAgentMappings.subscribe(()=>{sharedActiveMessageConsumer===u&&u.refresh()}),f=sharedRuntimeAuthority?.subscribeAuthority(()=>{sharedActiveMessageConsumer===u&&u.refresh()})??(()=>{}),w=new MessageClientTerminalStateRecovery({logger:e.logger,isCurrent:()=>{if(sharedActiveMessageConsumer!==u)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(r){e.logger.warn?.(`[beeos-claw] runtime Service delivery rebind failed after MessageClient recovery: ${r instanceof Error?r.message:String(r)}`)}}}});let R=l.getSnapshot().connection;sharedMSConnectionStatus.setIfCurrent(c,R);const v=l.subscribe(()=>{const r=l.getSnapshot();r.connection!==R&&(R=r.connection,sharedMSConnectionStatus.setIfCurrent(c,r.connection),"connected"===r.connection?(w.notifyConnected(),e.logger.info?.(`[beeos-claw] connection transport=message_service_realtime state=connected localAgentId=${p.getLocalAgentId()} principalId=${s.principalId}`)):"failed"===r.connection?(e.logger.warn?.(`[beeos-claw] connection transport=message_service_realtime state=failed principalId=${s.principalId} recoveryError=${r.recoveryError??"unknown"}`),w.notifyFailed()):"disconnected"!==r.connection&&"reconnecting"!==r.connection||e.logger.warn?.(`[beeos-claw] connection transport=message_service_realtime state=${r.connection} principalId=${s.principalId}; SDK owns reconnect/recovery`))});sharedActiveMessageConsumer=u,u.start();try{await l.connect()}catch(e){throw sharedActiveMessageConsumer===u&&(sharedActiveMessageConsumer=void 0),sharedMSConnectionStatus.resetIfCurrent(c),w.dispose(),await u.stop(),y(),f(),v(),await l.disconnect().catch(()=>{}),e}try{await p.rebindRuntimeDelivery()}catch(r){e.logger.warn?.(`[beeos-claw] runtime Service delivery rebind failed after MessageClient connect: ${r instanceof Error?r.message:String(r)}`)}return async()=>{sharedActiveMessageConsumer===u&&(sharedActiveMessageConsumer=void 0),sharedMSConnectionStatus.resetIfCurrent(c),w.dispose(),await u.stop(),f(),v(),await l.disconnect(),e.logger.info?.("[beeos-claw] MessageClient disconnected")}})},disconnect:async()=>{await sharedMessageClientOwner.release(r)}}}):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(!1!==R&&o.agentGatewayUrl){const r=e=>p.getGatewaySessionKeyForToolCall(e),t=e=>p.getMentionsForToolCall(e),n=(e,r)=>{p.broadcastNotification(e,r)},a=new TaskHandleRegistry;registerA2ATools(e,{agentGatewayUrl:o.agentGatewayUrl,agentKeys:agentKeys,logger:e.logger},a,r,t,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 r=sharedCanvasState;if(o.agentGatewayUrl&&agentKeys){let t;r.setLogger(e.logger);{const e=o.agentGatewayUrl,r=agentKeys;t=async()=>{const t=await agentFetch(`${e}/api/v1/canvas/token`,r,{method:"POST"});if(!t.ok){const e=await t.text().catch(()=>"");throw new Error(`Canvas token returned ${t.status}: ${e}`)}return t.json()}}const n=n=>{const a=new CanvasRelayClient({canvasRelayUrl:o.canvasRelayUrl,agentKeys:agentKeys,agentId:n.id,displayName:n.displayName,avatarUrl:n.avatarUrl,tokenProvider:t,onConnected:()=>p.flushPendingCanvasLinks(),onReconnect:()=>p.onRelayReconnected(),logger:e.logger});r.setRelayClient(a),r.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:()=>r.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 t={stateManager:r,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(r,t,o)=>(p.preMapToolCallSession(r),e(r,t));e.registerTool({name:RENDER_UI_TOOL_NAME,description:RENDER_UI_TOOL_DESCRIPTION,parameters:RENDER_UI_TOOL_SCHEMA,execute:c(createRenderUiHandler(t))}),e.registerTool({name:CLOSE_UI_TOOL_NAME,description:CLOSE_UI_TOOL_DESCRIPTION,parameters:CLOSE_UI_TOOL_SCHEMA,execute:c(createCloseUiHandler(t))}),p.setCanvasState(r,{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 d=p.getResourceRenderer();if(d){generateActionTools(l,e,async(e,r)=>p.gatewayRequest(e,r),d,e.logger)}const u=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,r)=>{if(r?.sessionKey){if(f.size>=h&&!f.has(r.sessionKey)){const e=f.keys().next().value;void 0!==e&&f.delete(e)}f.set(r.sessionKey,r.channelId),rememberDeliveryWorkspace(r.sessionKey,r.workspaceDir)}const t=isThirdPartyChannel(a,{sessionKey:r?.sessionKey,channelId:r?.channelId});return r?.sessionKey||t?{appendSystemContext:buildAppendSystemContext({thirdParty:t,canvasSystemPrompt:`${CANVAS_PRESENTATION_GATE}\n\n${CANVAS_SYSTEM_PROMPT}`,toolRoutingHint:u})}:{appendSystemContext:u}}),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,r)=>{if(r?.sessionKey&&p.setPendingToolCallSessionKey(r.sessionKey),!m.has(e.toolName))return;const t=r?.sessionKey?f.get(r.sessionKey):void 0,o=isThirdPartyChannel(a,{sessionKey:r?.sessionKey,channelId:t}),n=canvasToolBlockReason({thirdParty:o,hasSession:Boolean(r?.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 r=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(){r.start(),e.logger.info?.(`[beeos-claw] Terminal WS started on port ${o.terminalWsPort}`)},stop(){r.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(r.openclawConfig){const t=mirrorOpenClawConfig(r.openclawConfig);t.copied?e.logger.info?.(`[beeos-claw] mirrored openclaw config to ${t.destinationPath}`):e.logger.debug?.(`[beeos-claw] openclaw config mirror skipped: ${t.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 r=planPluginRegistration(e.registrationMode,_fullRuntimeRegistered);if("skip"!==r){_initializing=!0;try{if(!hasRuntimeReplyApi(e.runtime))throw e.logger.error?.("[beeos-claw] FATAL: OpenClaw runtime.channel.reply.dispatchReplyFromConfig not exposed. Upgrade OpenClaw or revert beeos-claw."),new Error("openclaw_runtime_reply_api_unavailable");const t=(r,t)=>{registerUploadTools(e,r,t),registerConnectorMcpProxy(e,r),registerArouterLatencyRouting(e),registerArouterMediaProviders(e)};if("capabilities"===r&&sharedPluginContext){if(cachedCapabilityTools.length>0){const r=resolveCapabilityToolReplay({currentRegisterTool:e.registerTool,wrappedRegisterTool:wrappedRegisterTool,originalRegisterTool:rawRegisterTool}),t=replayCachedPluginTools(t=>r.call(e,t),cachedCapabilityTools);return registerArouterLatencyRouting(e),registerArouterMediaProviders(e),void e.logger.info?.(`[beeos-claw] capability re-register mode=${e.registrationMode} tools_only count=${t}`)}const r={current:sharedAcpServer??null};return t(sharedPluginContext,r),registerServices(e,sharedPluginContext,r),void e.logger.info?.(`[beeos-claw] capability re-register mode=${e.registrationMode} capabilities_only`)}const o=initializePlugin(e);if(!o)return;const n={current:null};installUnhandledRejectionObserver(e,o.writeObs,n),ensureRegisterToolCache(e),cachedCapabilityTools.length=0,t(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,r)&&(_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{registerManagedConnectorTools}from"./connectors/managed-connector-tools.js";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{AgentGatewayClient,NodeRuntimeDeliveryPort,agentIdentityFromKeyPair,loadAgentKeyPair,signAgentMessage}from"@beeos-ai/cloud-harness-sdk";import{MessageServiceConversationRunBoundary}from"./runtime/message-service-conversation-run-boundary.js";import{AutomationTurnPolicy}from"./automation/turn-policy.js";import{registerAutomationTools}from"./automation/tools.js";import{extractBeeosConversationIdFromSessionKey}from"./runtime/openclaw-session-key-resolution.js";import{setOpenClawConfigSnapshot}from"./runtime/openclaw-session-model.js";import{BeeosClawMessageClientProcessOwner,createBeeosClawMessageTokenProvider}from"./message-client-composition.js";import{MessageProjectionInboundConsumer}from"./message-projection-inbound-consumer.js";import{MessageClientTerminalStateRecovery}from"./runtime/message-client-terminal-state-recovery.js";import{RuntimeAuthorityMessageBusLifecycle}from"./runtime/runtime-authority-message-bus-lifecycle.js";import{createNativeCloudChatComposition,nativeCloudChatAuthorityFromRuntimeAuthority}from"./runtime/native-cloud-chat-composition.js";import{MSConnectionStatusSnapshot}from"./runtime/ms-connection-status.js";import{FileInboundExecutionJournal}from"./inbound-execution-journal.js";import{completeA2ATask,registerA2ATools,TaskHandleRegistry}from"./a2a/tools.js";import{BEEOS_UPLOAD_TOOL_NAME,BEEOS_UPLOAD_TOOL_SCHEMA,BEEOS_UPLOAD_TOOL_DESCRIPTION,REQUEST_TIMEOUT_MS as BEEOS_UPLOAD_REQUEST_TIMEOUT_MS,executeUpload}from"./upload/tool.js";import{BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,BEEOS_DESKTOP_SCREENSHOT_TOOL_SCHEMA,BEEOS_DESKTOP_SCREENSHOT_TOOL_DESCRIPTION,executeDesktopScreenshot}from"./upload/desktop-screenshot-tool.js";import{BEEOS_LIST_FILES_TOOL_NAME,BEEOS_LIST_FILES_TOOL_SCHEMA,BEEOS_LIST_FILES_TOOL_DESCRIPTION,executeListFiles}from"./files/list-tool.js";import{BEEOS_FETCH_FILE_TOOL_NAME,BEEOS_FETCH_FILE_TOOL_SCHEMA,BEEOS_FETCH_FILE_TOOL_DESCRIPTION,executeFetchFile}from"./files/fetch-tool.js";import{writeUploadToolResult,cleanupUploadToolResultCache}from"./upload/result-cache.js";import{handleFileStage}from"./upload/file-stage.js";import{handleStatusRequest}from"./status.js";import{ACPServer}from"./acp-server.js";import{GatewayClient}from"./gateway-client.js";import{createObsEventWriter}from"./observability.js";import{resolvePluginVersion}from"./plugin-version.js";import{createTerminalWebSocketService}from"./terminal/websocket.js";import{TerminalManager}from"./terminal/session-manager.js";import{readDiscoveryCache,writeDiscoveryCache}from"./discovery-cache.js";import{setClaimedCloudRuntimeInstanceId,setUploadDeps}from"./upload/upload-file.js";import{registerLocalFileExtractor}from"./upload/local-file-extractors.js";import{browserScreenshotExtractor}from"./browser/screenshot-extractor.js";import{deliverableFileExtractor}from"./upload/deliverable-extractor.js";import{observeToolCallForDelivery,rememberDeliveryWorkspace}from"./upload/delivery-observe.js";import{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{fetchRuntimeLeaseAttempt}from"./runtime/message-service-runtime-authenticated-fetch.js";import{MessageServiceCronDeliveryHttpAuthority}from"./runtime/message-service-cron-delivery-http-authority.js";import{AgentMappingRegistry}from"./runtime/agent-mapping-registry.js";import{OpenClawRuntimeProcessOwner}from"./runtime/openclaw-runtime-process-owner.js";import{AgentGatewayHttpProjectionTransport,AgentGatewayTemplateOriginReporter,AgentProjectionProduction,OpenClawAgentProjectionSource}from"./runtime/agent-projection-production.js";import{MessageServiceRunOutputChannel}from"./runtime/message-service-run-output-channel.js";import{AssistantMessageCommitRouter}from"./runtime/assistant-message-commit-router.js";import{ToolResultObservationRouter}from"./runtime/tool-result-observation-router.js";import{ModelCallObservationRouter,registerModelCallObservationHooks}from"./runtime/model-call-observability.js";import{registerArouterLatencyRouting}from"./runtime/arouter-latency-routing.js";import{createPeerRunOutputRouterFactory}from"./runtime/run-output-composition.js";const PLUGIN_VERSION=resolvePluginVersion();let agentKeys=null,agentGateway=null,sharedCanvasState=null,sharedAcpServer=null;const sharedSessionWriteGate=new SessionWriteGate,sharedPromptRunStore=new PromptRunStore,sharedAutomationTurnPolicy=new AutomationTurnPolicy;let lastOpenclawConfig;const sharedMcpNativeProjectionNudge=createMcpNativeProjectionNudge({getActiveImRunCount:()=>sharedPromptRunStore.size(),nudge:()=>{sharedAcpServer?.nudgeMcpNativeProjection()}}),sharedImHotPathDeferral=createImHotPathDeferral({getActiveImRunCount:()=>sharedPromptRunStore.size()});sharedPromptRunStore.setOnBecameIdle(()=>{sharedMcpNativeProjectionNudge.flushIfIdle({fingerprint:fingerprintMcpServers(lastOpenclawConfig)}),sharedImHotPathDeferral.notifyIdle()});const sharedAssistantMessageCommitRouter=new AssistantMessageCommitRouter,sharedToolResultObservationRouter=new ToolResultObservationRouter,sharedModelCallObservationRouter=new ModelCallObservationRouter;let sharedSessionMutationCoordinator,sharedRuntimeAuthority,sharedNativeCloudChat,warmClaimAttached=!1,sharedWriteObs=()=>{};const sharedMSConnectionStatus=new MSConnectionStatusSnapshot,sharedAgentMappings=new AgentMappingRegistry;let sharedGatewayClient,sharedRuntimeOwner,sharedAgentProjection,sharedRuntimeAgentCapabilities,sharedMcpProjection,sharedMcpCredentialVault;const sharedMessageClientOwner=new BeeosClawMessageClientProcessOwner;let sharedActiveMessageConsumer,sharedInboundExecutionJournal;const sharedTerminalManager=new TerminalManager;let _initializing=!1,_pluginRegisteredAt=0,_fullRuntimeRegistered=!1;const cachedCapabilityTools=[];let rawRegisterTool,wrappedRegisterTool;const ensureRegisterToolCache=e=>{rawRegisterTool||(rawRegisterTool=e.registerTool.bind(e),wrappedRegisterTool=e=>(cachedCapabilityTools.push(e),rawRegisterTool(e)),e.registerTool=wrappedRegisterTool)};function agentKeyPairToIdentity(e){return{publicKeyBase64:()=>Buffer.from(e.publicKey).toString("base64"),sign:async t=>signAgentMessage(t,e.privateKey)}}let sharedPluginContext=null,unhandledRejectionObserverInstalled=!1;function installUnhandledRejectionObserver(e,t,r){unhandledRejectionObserverInstalled||(unhandledRejectionObserverInstalled=!0,process.on("unhandledRejection",r=>{const o=r instanceof Error?r.message:String(r),a=r instanceof Error?r.stack:void 0;e.logger.error?.(`[beeos-claw] unhandledRejection: ${o}${a?`\n${a}`:""}`),t({component:"plugin",domain:"fatal",name:"unhandled_rejection",severity:"error",summary:o,error:{code:"unhandled_rejection",message:o,...a?{stack:a}:{}}})}),process.on("uncaughtException",r=>{const o=r instanceof Error?r.message:String(r);e.logger.error?.(`[beeos-claw] uncaughtException: ${r instanceof Error?r.stack??r.message:String(r)}`),t({component:"plugin",domain:"fatal",name:"uncaught_exception",severity:"error",summary:o,error:{code:"uncaught_exception",message:o}})}))}function initializePlugin(e){let t,r;try{t=e.runtime?.config?.loadConfig?.()}catch{}try{r=resolveConfigWithMeta({pluginConfig:e.pluginConfig??{},openclawConfig:t})}catch(t){return e.logger.error?.(`[beeos-claw] Failed to resolve config: ${t instanceof Error?t.message:String(t)}`),null}const o=r.config,a=buildThirdPartyChannelSet(t);a.size>0&&e.logger.info?.(`[beeos-claw] Third-party channels detected: ${[...a].join(", ")}`);const n=o.log.enabled?createObsEventWriter({dir:o.log.dir,redaction:{gatewayToken:o.gateway.token},logger:e.logger}):()=>{};n({component:"plugin",domain:"lifecycle",name:"lifecycle.startup",severity:"info",payload:{pluginVersion:PLUGIN_VERSION,pid:process.pid,nodeVersion:process.version,cwd:process.cwd()}}),n({component:"plugin",domain:"config",name:"config.resolved",severity:"info",payload:{config:o,sources:r.sources,openclawConfigPath:r.openclawConfigPath}});for(const t of r.validation)n({component:"plugin",domain:"config",name:"config.validation",severity:t.severity,summary:t.message,error:{code:t.code,message:t.message,nextSteps:t.nextSteps}}),"error"===t.severity?e.logger.error?.(`[beeos-claw] ${t.message}`):e.logger.warn?.(`[beeos-claw] ${t.message}`);if(r.validation.some(e=>"error"===e.severity)&&e.logger.error?.("[beeos-claw] Plugin has configuration errors — some features may not work."),o.keyFile)try{agentKeys=loadAgentKeyPair(o.keyFile),agentGateway=o.agentGatewayUrl?new AgentGatewayClient({baseUrl:o.agentGatewayUrl,identity:agentIdentityFromKeyPair(agentKeys),onRetry:({method:t,path:r,attempt:o,delayMs:a,error:n})=>e.logger.warn?.(`[beeos-claw] Agent Gateway ${t} ${r} retry ${o} in ${a}ms: ${n instanceof Error?n.message:String(n)}`)}):null;const t=Buffer.from(agentKeys.publicKey).toString("base64");e.logger.info?.(`[beeos-claw] v${PLUGIN_VERSION} registering (publicKey: ${t})`)}catch(t){e.logger.warn?.(`[beeos-claw] Failed to load agent key pair: ${t}`),e.logger.info?.(`[beeos-claw] v${PLUGIN_VERSION} registering (no key pair — signed requests disabled)`)}else e.logger.info?.(`[beeos-claw] v${PLUGIN_VERSION} registering (no keyFile configured)`);return agentGateway&&(setUploadDeps({gateway:agentGateway,logger:e.logger}),registerLocalFileExtractor(browserScreenshotExtractor),registerLocalFileExtractor(deliverableFileExtractor),e.logger.info?.("[beeos-claw] Upload deps + local file extractors registered")),lastOpenclawConfig=t,sharedWriteObs=n,setOpenClawConfigSnapshot(t),{cfg:o,writeObs:n,thirdPartyChannels:a,openclawConfig:t}}function registerUploadTools(e,t,r){const{cfg:o,writeObs:a}=t,n=Boolean(pluginCloudRuntimeTarget(e));if(n){if(!e.on)throw new Error("native output Files Host hook unavailable");e.on("before_tool_call",(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=n?consumeNativeOutputTool(t):void 0,l=await executeUpload(r,agentGateway,i,s?(e,t)=>uploadNativeOutputFile(e,o.agentGatewayUrl,s,t,i,BEEOS_UPLOAD_REQUEST_TIMEOUT_MS):void 0,e.logger);return e.logger.debug?.(`[beeos_upload_file] toolCallId=${t} ok=${l.ok}`),a({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,o){e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${t} params=${JSON.stringify(r)}`);const n=await executeDesktopScreenshot(r,agentGateway,o);return e.logger.debug?.(`[beeos_desktop_screenshot] toolCallId=${t} ok=${n.ok}`),a({component:"desktop-screenshot-tool",domain:"tool",name:n.ok?"desktop_screenshot.success":"desktop_screenshot.failure",severity:n.ok?"info":"warn",payload:{toolCallId:t,ok:n.ok,path:n.path,fileCount:n.files?.length??0,error:n.error}}),(async r=>{try{await writeUploadToolResult(t,BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME,r),await cleanupUploadToolResultCache()}catch(r){e.logger.warn?.(`[beeos_desktop_screenshot] persist cache failed toolCallId=${t}: ${String(r)}`)}return r})(n)}}),e.registerHttpRoute({path:"/beeos/files/stage",auth:"gateway",async handler(e,r){await handleFileStage(e,r,t.cfg)}}),e.registerHttpRoute({path:"/beeos/status",auth:"plugin",handler(e,t){handleStatusRequest(e,t,{publicKey:agentKeys?.publicKey??null,pluginVersion:PLUGIN_VERSION})}}),e.registerTool({name:BEEOS_LIST_FILES_TOOL_NAME,description:BEEOS_LIST_FILES_TOOL_DESCRIPTION,parameters:BEEOS_LIST_FILES_TOOL_SCHEMA,async execute(t,r,o){e.logger.debug?.(`[beeos_list_files] toolCallId=${t} params=${JSON.stringify(r)}`);const n=await executeListFiles(r,agentGateway,o);return a({component:"file-list-tool",domain:"tool",name:n.ok?"list_files.success":"list_files.failure",severity:n.ok?"info":"warn",payload:{toolCallId:t,ok:n.ok,fileCount:n.files?.length??0,error:n.error}}),n}}),e.registerTool({name:BEEOS_FETCH_FILE_TOOL_NAME,description:BEEOS_FETCH_FILE_TOOL_DESCRIPTION,parameters:BEEOS_FETCH_FILE_TOOL_SCHEMA,async execute(t,r,o){e.logger.debug?.(`[beeos_fetch_file] toolCallId=${t} params=${JSON.stringify(r)}`);const n=await executeFetchFile(r,agentGateway,{signal:o,resolvePath:e.resolvePath});return a({component:"file-fetch-tool",domain:"tool",name:n.ok?"fetch_file.success":"fetch_file.failure",severity:n.ok?"info":"warn",payload:{toolCallId:t,ok:n.ok,path:n.path,size:n.size,error:n.error}}),n}})}function registerConnectorMcpProxy(e,t){e.registerHttpRoute({path:CONNECTOR_MCP_PROXY_PATH,auth:"plugin",async handler(t,r){await handleConnectorMcpRequest(t,r,{gateway:agentGateway,logger:e.logger})}})}function registerServices(e,t,r){const{cfg:o,writeObs:a,thirdPartyChannels:n}=t;if(sharedAutomationTurnPolicy.disable(),"function"==typeof e.on)try{e.on("before_tool_call",(e,t)=>sharedAutomationTurnPolicy.check(e.toolName,{sessionKey:t?.sessionKey,runId:t?.runId??e.runId}),{priority:100}),sharedAutomationTurnPolicy.enable()}catch{e.logger.warn?.("[beeos-claw] Automation Wake disabled: tool guard unavailable")}if("function"!=typeof e.on){if(o.messageBus.enabled)throw new Error("openclaw_before_message_write_hook_unavailable")}else registerModelCallObservationHooks((t,r)=>e.on(t,r),sharedModelCallObservationRouter),e.on("before_message_write",(t,r)=>{const o=t.sessionKey??r.sessionKey;if(!o)return void e.logger.debug?.("[before_message_write] ignored assistant write without sessionKey");sharedAssistantMessageCommitRouter.route(o,t.message)||e.logger.debug?.(`[before_message_write] no active IM commit target sessionKey=${o} active_targets=${sharedAssistantMessageCommitRouter.size()}`)}),e.on("after_tool_call",(t,r)=>{const o=r.sessionKey,a=t.toolCallId??r.toolCallId,n=t.toolName||r.toolName;if(!o||!a||!n)return void e.logger.debug?.(`[after_tool_call] ignored structured result without correlation sessionKey=${o??"missing"} toolCallId=${a??"missing"}`);observeToolCallForDelivery(t,o);sharedToolResultObservationRouter.route(o,{toolCallId:a,toolName:n,rawResult:t.result,isError:Boolean(t.error)})||e.logger.debug?.(`[after_tool_call] no active IM observation target sessionKey=${o} active_targets=${sharedToolResultObservationRouter.size()}`)});const i=agentKeys?Buffer.from(agentKeys.publicKey).toString("base64"):void 0,s=join(process.env.OPENCLAW_HOME||join(homedir(),".openclaw"),"beeos"),l=sharedInboundExecutionJournal??=new FileInboundExecutionJournal(join(s,"inbound-execution-journal.v1.jsonl"));sharedMcpProjection??=new OpenClawNativeMcpProjection,!sharedMcpCredentialVault&&agentKeys&&i&&(sharedMcpCredentialVault=new LocalEncryptedCredentialReferenceVault(join(s,"mcp-credential-vault.json"),i,agentKeys.privateKey));const c=pluginCloudRuntimeTarget(e);if(c&&(!agentKeys||!agentGateway))throw new Error("Cloud runtime authority requires an agent identity and gateway transport");const u=sharedRuntimeAuthority?.cloudTargetInstanceId;if(u&&c&&u!==c)throw new Error("Cloud runtime authority target changed during process lifetime");if(sharedRuntimeAuthority&&!u&&c&&sharedRuntimeAuthority.bindCloudTarget(c),!sharedRuntimeAuthority&&agentKeys&&agentGateway&&(sharedRuntimeAuthority=new RuntimeProductionAuthority({stateDirectory:s,gateway:agentGateway,keys:agentKeys,targetInstanceId:c,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,...o.messageBus.enabled&&sharedAutomationTurnPolicy.isReady()&&agentGateway?{automationWake:!0}:{}},!sharedAgentProjection&&sharedRuntimeAuthority&&agentGateway){const t=sharedRuntimeAuthority;sharedAgentProjection=new AgentProjectionProduction({authority:t,stateFile:join(t.stateDirectory,"runtime-agent-projection.json"),journal:t.journal,identities:t.identities,source:new OpenClawAgentProjectionSource(()=>sharedGatewayClient),transport:new AgentGatewayHttpProjectionTransport({gateway:agentGateway,getRuntimeLeaseCredential:e=>{const r=t.authorityLease;if(!r||r.instanceId!==e.instanceId||r.leaseId!==e.leaseId||r.runtimeEpoch!==e.runtimeEpoch||r.handlerIdentity!==e.handlerIdentity)throw new Error("agent projection fenced by current runtime lease");return r.runtimeLeaseCredential},onAccepted:t=>{0!==t.size&&sharedAgentMappings.replace(t).catch(t=>{e.logger.warn?.("[agent-projection] mapping publication failed: "+(t instanceof Error?t.message:String(t)))})}}),capabilities:sharedRuntimeAgentCapabilities,logger:e.logger})}sharedRuntimeOwner??=new OpenClawRuntimeProcessOwner(sharedGatewayClient,sharedAgentProjection,e.logger);const g=sharedRuntimeOwner;sharedSessionMutationCoordinator??=new SessionMutationCoordinator(sharedSessionWriteGate,new OpenClawSessionWriteQuiescence(e.logger,{agentId:o.gateway.agentId||"main"}),e.logger,{onRecoveryRequired:t=>{scheduleProcessRuntimeRestart(t,e.logger)}});const d=sharedSessionMutationCoordinator;if(!sharedAcpServer){const t=sharedRuntimeAuthority&&agentGateway?new AgentGatewayTemplateOriginReporter({gateway:agentGateway}):void 0;sharedAcpServer=new ACPServer(o,e.logger,d,a,agentGateway??void 0,i,n,sharedTerminalManager,sharedRuntimeAuthority,void 0,sharedMcpProjection,sharedMcpCredentialVault,{gateway:g.client,agentProjection:sharedAgentProjection,markAgentProjectionDirty:()=>sharedAgentProjection?.markDirty(),templateOriginReporter:t,agentMappings:sharedAgentMappings,agentCapabilities:sharedRuntimeAgentCapabilities,createRunOutputRouter:createPeerRunOutputRouterFactory(new MessageServiceRunOutputChannel({getClient:()=>sharedMessageClientOwner.current?.client??null,logger:e.logger,writeObs:a})),runExclusive:(t,r,o)=>sharedImHotPathDeferral.runExclusive(t,r,e.logger,o)})}const m=sharedAcpServer,p=()=>sharedAgentMappings.snapshot()?.values().next().value;r.current=m,sharedMcpNativeProjectionNudge.request({registrationMode:e.registrationMode,fingerprint:fingerprintMcpServers(t.openclawConfig),logger:e.logger});const y=sharedPromptRunStore,{enabled:h,principalId:f,a2aEnabled:v}=o.messageBus;let w;!c&&o.agentGatewayUrl&&agentKeys&&(w=createBeeosClawMessageTokenProvider({agentGatewayUrl:o.agentGatewayUrl,identity:agentKeyPairToIdentity(agentKeys)}));const C=process.env.MESSAGE_RUNTIME_DELIVERY_KEY?.trim(),R=f||process.env.BEEOS_PRINCIPAL_ID||"",b=w?sharedMessageClientOwner.configure({tokenProvider:w,identityId:R,...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=c&&o.messageBus.serviceUrl&&sharedRuntimeAuthority?new NodeRuntimeDeliveryPort({serviceOrigin:async()=>o.messageBus.serviceUrl},{currentLease:()=>{const e=sharedRuntimeAuthority?.authorityLease,t=sharedRuntimeAuthority?.currentConsumerBinding();return e&&t&&e.instanceId===c?{...e,journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}:null},subscribeAuthority:e=>sharedRuntimeAuthority.subscribeAuthority(e)}):void 0;attachNativeCloudChat(e,o);const _=sharedRuntimeAuthority,O=o.messageBus.serviceUrl;b&&_&&O&&C?m.setCronConversationDelivery({deliver:async e=>{const t=_.authorityLease;if(!t)throw new Error("current runtime authority lease unavailable for cron delivery");const r=new MessageServiceCronDeliveryHttpAuthority({messageServiceUrl:O,scopedDeliveryKey:C,fetchAuthorized:(e,t)=>fetchRuntimeLeaseAttempt(e,t??{})});return await r.deliver({...e,runtimeLeaseCredential:t.runtimeLeaseCredential})}}):m.setCronConversationDelivery(void 0);const E=sharedRuntimeAuthority?.journal??new FileRuntimeCommandJournal(join(s,"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)}`)}),A=g.createRegistrationToken();e.registerService({id:"beeos-acp",async start(){const t=Date.now(),r=_pluginRegisteredAt?t-_pluginRegisteredAt:-1;e.logger.info?.(`[beeos-claw] beeos-acp service start() begin, sincePluginRegister=${r}ms, bridge.url=${o.bridge.url||"(empty)"}`);const a=await createRuntimeServiceProductionCandidate({...agentGateway?{authorizationAdapter:new AgentGatewayGrantJwksReadinessAdapter({gateway:agentGateway})}:{},onGrantJwksWarm:t=>{t.ready?e.logger.info?.("[beeos-claw] Gateway grant keyset loaded"):e.logger.warn?.(`[beeos-claw] Gateway grant keyset not ready yet (attempt ${t.attempt}): ${t.error instanceof Error?t.error.message:String(t.error)}`)},...b&&agentGateway&&C?{transportAdapter:new RuntimeServiceTransportReadinessAdapter({gateway:agentGateway,messageService:b.nodeTransport,messageClient:b.client,configuredServiceUrl:o.messageBus.serviceUrl,scopedDeliveryKey:C})}:{},...S&&agentGateway&&o.messageBus.serviceUrl?{cloudTransportAdapter:new CloudRuntimeServiceTransportReadinessAdapter({gateway:agentGateway,configuredServiceUrl:o.messageBus.serviceUrl,runtimeDelivery:S,...sharedNativeCloudChat?{sessionNewConversation:sharedNativeCloudChat.sessionNewConversation,nativePrompt:{http:sharedNativeCloudChat.http,inputFiles:new NativeInputFilesHttpClient(o.agentGatewayUrl,()=>sharedRuntimeAuthority.authorityLease,(e,t)=>fetch(e,t)),runBoundary:new MessageServiceConversationRunBoundary({transport:{start:e=>S.startConversationRun(e),finish:e=>S.finishConversationRun(e)}}),host:{resolveNativePromptSessionKey:(e,t)=>m.resolveNativePromptSessionKey(e,t),prepareNativePromptModel:(e,t,r)=>m.prepareNativePromptModel(e,t,r),runtime:e.runtime,pluginConfig:o,logger:e.logger,promptRunStore:y,assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:d,abortTransport:{chatAbort:(e,t)=>m.chatAbort(e,t)},activeRunAuthority:m.getActiveRunAuthority(),waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{})}}}:{}})}:{},commandJournal:E,poisonJournal:new FileRuntimePoisonDeliveryJournal(join(s,"runtime-poison-deliveries.json")),onConsumerDeliveryError:t=>{const r=null!==t&&"object"==typeof t?t:{},o=e=>"string"==typeof e&&e.length>0&&e.length<=256&&!/[\u0000-\u001f\u007f]/.test(e)?JSON.stringify(e):JSON.stringify("unavailable"),a="string"==typeof r.code&&/^[A-Za-z0-9_.:-]{1,64}$/.test(r.code)?r.code:"unavailable",n="number"==typeof r.status&&Number.isInteger(r.status)&&r.status>=100&&r.status<=599?String(r.status):"unavailable";e.logger.error?.(`[runtime-service] delivery worker failed before acknowledgement; delivery retained for retry: operation_id=${o(r.operationId)} delivery_id=${o(r.deliveryId)} code=${a} status=${n}`)},onConsumerLeaseStarvation:({starvedForMs:t,recovered:r})=>{const o=Math.round(t/1e3);r?e.logger.info?.(`[runtime-service] runtime authority lease restored after ${o}s without delivery reads`):e.logger.warn?.(`[runtime-service] no runtime authority lease for ${o}s; delivery reads suspended, queued runtime operations (model switch, session control) will not be consumed`)},onConsumerRequestFailure:t=>e.logger.error?.(`[runtime-service] request failed operationId=${t.operationId} method=${t.method}: ${t.error instanceof Error?t.error.stack??t.error.message:String(t.error)}`)});if(sharedRuntimeAuthority?.setRuntimeServiceMethods("ready"===a.status?a.serviceMethods:[]),sharedRuntimeAuthority?.setRuntimeResourceBindingContractRevision("ready"===a.status?a.resourceBindingContractRevision:void 0),m.setRuntimeRpcConsumerFactory("ready"===a.status?a.factory:void 0),"unavailable"===a.status?e.logger.warn?.("[runtime-service] capability fenced: "+a.blockers.map(e=>e.id).join(",")):a.capabilityBlockers.length&&e.logger.warn?.("[runtime-service] method capability fenced: "+a.capabilityBlockers.map(e=>e.method).join(",")),!o.bridge.url&&agentGateway){const t=Date.now(),r=await agentGateway.bridge.config();if(e.logger.info?.(`[beeos-claw] bridge discovery took ${Date.now()-t}ms result=${r?.url??"null"}`),r)o.bridge.url=r.url,writeDiscoveryCache({bridge:{url:r.url,discoveredAt:Date.now()}}),e.logger.info?.(`[beeos-claw] Bridge URL discovered from Agent Gateway: ${r.url}`);else{const t=readDiscoveryCache();t?.bridge?.url?(o.bridge.url=t.bridge.url,e.logger.info?.(`[beeos-claw] Bridge URL from cache (GW unreachable): ${t.bridge.url}`)):e.logger.debug?.("[beeos-claw] Bridge URL not available (no GW, no cache) — bridge disabled")}}await g.acquire(A);try{await m.start(o.bridge.url||void 0)}catch(e){throw await g.release(A),e}e.logger.info?.(`[beeos-claw] ACP Server started (total service start: ${Date.now()-t}ms)`)},async stop(){try{await g.release(A)}finally{await m.stop()}await E.checkpoint(),e.logger.info?.("[runtime-service] command journal checkpoint completed"),e.logger.info?.("[beeos-claw] ACP Server stopped")}});if(h&&void 0!==w&&w){const t=sharedMessageClientOwner.createRegistrationToken(),r=async(e,t)=>{const r=await w(e);if(!r.identityId||r.identityId!==e)throw new Error("Message SDK token identity did not match the current runtime authority");return{principalId:e,runtimeEpoch:t}},o=(e,t,r)=>({getLocalAgentId:()=>t,resolveLocalAgentId:e=>e===r?t:void 0,getDefaultPlatformAgent:()=>({instanceId:e.principalId}),ensureImInboundSession:(e,t,r,o)=>{m.ensureImInboundSession(e,t,r,o)},chatAbort:(e,t)=>m.chatAbort(e,t)}),n=sharedRuntimeAuthority?new RuntimeAuthorityMessageBusLifecycle({authority:sharedRuntimeAuthority,logger:e.logger,bus:{connect:async n=>{await sharedMessageClientOwner.acquire(t,async t=>{const i=await r(n.instanceId,n.runtimeEpoch),s=t.client,c={leaseId:n.leaseId,runtimeEpoch:n.runtimeEpoch};sharedMSConnectionStatus.bind(c);const u=new Map,g=new MessageProjectionInboundConsumer({client:s,bindings:()=>{const t=sharedRuntimeAuthority?.authorityLease;if(!t||t.instanceId!==i.principalId||t.runtimeEpoch!==i.runtimeEpoch)return[];const r=sharedAgentMappings.snapshot();return r?[...r.entries()].flatMap(([r,n])=>{if(!n.id||n.instanceId!==i.principalId)return[];let l=u.get(n.id);return l&&l.localAgentId===r||(l={localAgentId:r,inbound:createImInboundHandler({automationTurnPolicy:sharedAutomationTurnPolicy,runtime:e.runtime,pluginConfig:e.pluginConfig,client:s,localServer:o(i,r,n.id),promptRunStore:y,waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{}),assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:d,logger:e.logger,writeObs:a,principalIdOverride:i.principalId,activeRunAuthority:m.getActiveRunAuthority(),applyTurnModel:(e,t)=>m.applyImTurnModel(e,t),restoreTurnModel:e=>m.restoreImTurnModel(e),...agentGateway?{completeA2ATask:(t,r,o)=>completeA2ATask({gateway:agentGateway,logger:e.logger},t,r,o)}:{}})},u.set(n.id,l)),[{principalId:i.principalId,targetAgentId:n.id,runtimeEpoch:t.runtimeEpoch,inbound:l.inbound}]}):[]},executionJournal:l,logger:e.logger}),p=sharedAgentMappings.subscribe(()=>{sharedActiveMessageConsumer===g&&g.refresh()}),h=sharedRuntimeAuthority?.subscribeAuthority(()=>{sharedActiveMessageConsumer===g&&g.refresh()})??(()=>{}),f=new MessageClientTerminalStateRecovery({logger:e.logger,isCurrent:()=>{if(sharedActiveMessageConsumer!==g)return!1;const e=sharedRuntimeAuthority?.authorityLease;return null!=e&&e.instanceId===i.principalId&&e.runtimeEpoch===i.runtimeEpoch&&e.leaseId===n.leaseId&&e.handlerIdentity===n.handlerIdentity},reconnect:async()=>{if("failed"===s.getSnapshot().connection){await s.connect();try{await m.rebindRuntimeDelivery()}catch(t){e.logger.warn?.(`[beeos-claw] runtime Service delivery rebind failed after MessageClient recovery: ${t instanceof Error?t.message:String(t)}`)}}}});let v=s.getSnapshot().connection;sharedMSConnectionStatus.setIfCurrent(c,v);const w=s.subscribe(()=>{const t=s.getSnapshot();t.connection!==v&&(v=t.connection,sharedMSConnectionStatus.setIfCurrent(c,t.connection),"connected"===t.connection?(f.notifyConnected(),e.logger.info?.(`[beeos-claw] connection transport=message_service_realtime state=connected localAgentId=${m.getLocalAgentId()} principalId=${i.principalId}`)):"failed"===t.connection?(e.logger.warn?.(`[beeos-claw] connection transport=message_service_realtime state=failed principalId=${i.principalId} recoveryError=${t.recoveryError??"unknown"}`),f.notifyFailed()):"disconnected"!==t.connection&&"reconnecting"!==t.connection||e.logger.warn?.(`[beeos-claw] connection transport=message_service_realtime state=${t.connection} principalId=${i.principalId}; SDK owns reconnect/recovery`))});sharedActiveMessageConsumer=g,g.start();try{await s.connect()}catch(e){throw sharedActiveMessageConsumer===g&&(sharedActiveMessageConsumer=void 0),sharedMSConnectionStatus.resetIfCurrent(c),f.dispose(),await g.stop(),p(),h(),w(),await s.disconnect().catch(()=>{}),e}try{await m.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===g&&(sharedActiveMessageConsumer=void 0),sharedMSConnectionStatus.resetIfCurrent(c),f.dispose(),await g.stop(),h(),w(),await s.disconnect(),e.logger.info?.("[beeos-claw] MessageClient disconnected")}})},disconnect:async()=>{await sharedMessageClientOwner.release(t)}}}):void 0;e.registerService({id:"beeos-message-bus",async start(){n?n.start():e.logger.warn?.("[beeos-claw] Message bus requires runtime authority; waiting is unavailable without Agent Gateway runtime identity")},async stop(){await(n?.stop())}})}else h?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=${h})`);if(attachNativeCloudChat(e,o),o.messageBus.enabled&&c&&!sharedNativeCloudChat&&e.logger.warn?.("[beeos-claw] Cloud message bus enabled but native composition unavailable (messageBus.serviceUrl or runtime authority missing) — disabled"),!1!==v&&agentGateway){const t=e=>m.getGatewaySessionKeyForToolCall(e),r=e=>m.getMentionsForToolCall(e),o=(e,t)=>{m.broadcastNotification(e,t)},a=new TaskHandleRegistry;registerA2ATools(e,{gateway:agentGateway,logger:e.logger},a,t,r,o,()=>p()?.instanceId),e.logger.info?.("[beeos-claw] A2A tools registered (beeos_discover_agents, beeos_call_agent) via REST")}if(agentGateway&&(registerAutomationTools(e,{gateway:agentGateway,logger:e.logger,getDefaultAgent:()=>{const e=p();return e?{id:e.id,instanceId:e.instanceId}:void 0},getCurrentConversationId:e=>{const t=m.getGatewaySessionKeyForToolCall(e);return t?extractBeeosConversationIdFromSessionKey(t):void 0}}),e.logger.info?.("[beeos-claw] Automation tools registered (create/create_webhook/capabilities/preflight/list/get/run/runs/get_run)")),o.canvasEnabled){sharedCanvasState||(sharedCanvasState=new CanvasStateManager);const t=sharedCanvasState;if(agentGateway&&agentKeys){t.setLogger(e.logger);const r=()=>agentGateway.canvas.token(),a=a=>{const n=new CanvasRelayClient({canvasRelayUrl:o.canvasRelayUrl,agentKeys:agentKeys,agentId:a.id,displayName:a.displayName,avatarUrl:a.avatarUrl,tokenProvider:r,onConnected:()=>m.flushPendingCanvasLinks(),onReconnect:()=>m.onRelayReconnected(),logger:e.logger});t.setRelayClient(n),t.setAgentId(a.id),m.wireRelayActionHandler(),n.connect(),e.logger.info?.(`[beeos-claw] Canvas Relay multiplexed client connected (agentId=${a.id}, name=${a.name??"none"})`)};e.registerService(createCanvasRelayService({getAgent:p,onceAgentReady:e=>sharedAgentMappings.onceReady(e),initRelay:a,stopRelay:()=>t.getRelayClient()?.disconnect(),logger:e.logger})),e.logger.info?.("[beeos-claw] Canvas Relay configured")}else e.logger.warn?.("[beeos-claw] Canvas Relay unavailable: agentGatewayUrl or agentKeys missing");const r={stateManager:t,logger:e.logger,writeObs:e=>a(e),getActiveSessionId:e=>m.getSessionIdForToolCall(e),getPlatformAgentId:e=>m.getPlatformAgentIdForToolCall(e),getGatewaySessionKey:e=>m.getGatewaySessionKeyForToolCall(e),waitForAgentSync:()=>sharedAgentMappings.waitForSynchronization()},i=new FormSchemaRegistry,s=buildCronSchemas(n);i.register(s.create),i.register(s.update);const l=new ResourceDescriptorRegistry;l.register(CRON_RESOURCE);const c=e=>async(t,r,o)=>(m.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))}),m.setCanvasState(t,{schemaRegistry:i,descriptorRegistry:l});const u=m.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=m.getResourceRenderer();if(g){generateActionTools(l,e,async(e,t)=>m.gatewayRequest(e,t),g,e.logger)}const d=buildToolRoutingHint(BEEOS_FILE_RESOURCE_ROUTING_RULE,BEEOS_DESKTOP_SCREENSHOT_TOOL_NAME),y=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(n,{sessionKey:t?.sessionKey,channelId:t?.channelId});return t?.sessionKey||r?{appendSystemContext:buildAppendSystemContext({thirdParty:r,canvasSystemPrompt:`${CANVAS_PRESENTATION_GATE}\n\n${CANVAS_SYSTEM_PROMPT}`,toolRoutingHint: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&&m.setPendingToolCallSessionKey(t.sessionKey),!y.has(e.toolName))return;const r=t?.sessionKey?f.get(t.sessionKey):void 0,o=isThirdPartyChannel(n,{sessionKey:t?.sessionKey,channelId:r}),a=canvasToolBlockReason({thirdParty:o,hasSession:Boolean(t?.sessionKey)});return a?{block:!0,blockReason:a}:void 0}),e.logger.debug?.("[beeos-claw] Canvas tool guard registered: before_tool_call")}catch{e.logger.debug?.("[beeos-claw] before_tool_call hook not supported")}}e.logger.info?.("[beeos-claw] Canvas tools registered (render_ui, close_ui, render_form + auto-action tools)")}else e.logger.info?.("[beeos-claw] Canvas disabled by config (canvasEnabled=false)");if(o.bridge.shell.enabled&&!0===o.legacyTerminalWsEnabled){const t=createTerminalWebSocketService({config:{port:o.terminalWsPort,token:agentKeys?Buffer.from(agentKeys.publicKey).toString("base64"):"",allowedOrigins:o.terminalWsAllowedOrigins},terminalMgr:sharedTerminalManager,logger:e.logger,writeObs:a});e.registerService({id:"beeos-terminal-ws",start(){t.start(),e.logger.info?.(`[beeos-claw] Terminal WS started on port ${o.terminalWsPort}`)},stop(){t.stop(),e.logger.info?.("[beeos-claw] Terminal WS stopped")}})}else o.bridge.shell.enabled?e.logger.info?.("[beeos-claw] Legacy static-token Terminal WS disabled (default)"):e.logger.info?.("[beeos-claw] Terminal/shell disabled by config (bridge.shell.enabled=false)");if(t.openclawConfig){const r=mirrorOpenClawConfig(t.openclawConfig);r.copied?e.logger.info?.(`[beeos-claw] mirrored openclaw config to ${r.destinationPath}`):e.logger.debug?.(`[beeos-claw] openclaw config mirror skipped: ${r.reason}`)}}function pluginCloudRuntimeTarget(e){const t=e.pluginConfig?.cloudRuntimeInstanceId,r=cloudRuntimeTargetInstanceId("string"==typeof t?t:void 0);return setClaimedCloudRuntimeInstanceId(r),r}function attachNativeCloudChat(e,t){if(warmClaimAttached)return sharedNativeCloudChat;const r=sharedRuntimeAuthority,o=t.messageBus.serviceUrl,a=sharedAcpServer,n=sharedSessionMutationCoordinator;if(!(r&&r.cloudTargetInstanceId&&o&&a&&n))return sharedNativeCloudChat;const i=sharedNativeCloudChat??createNativeCloudChatComposition({authority:nativeCloudChatAuthorityFromRuntimeAuthority(r),serviceUrl:o,logger:e.logger});if(sharedNativeCloudChat=i,!t.messageBus.enabled)return i;const s=_fullRuntimeRegistered,l=i,c=r;let u;const g=new Map,d=new RuntimeAuthorityMessageBusLifecycle({authority:c,logger:e.logger,bus:{connect:async t=>{u?.(),g.clear(),u=l.adapter.listen({eventTypes:["message.created"]},r=>{const o=(r.content??{}).metadata??{},i="string"==typeof o.target_agent_id?o.target_agent_id:"",s=i?((t,r)=>{const o=sharedAgentMappings.snapshot();if(o)for(const[i,s]of o.entries()){if(s.id!==r)continue;if(s.instanceId!==t.instanceId)continue;const o=`${i}\0${s.id}`;let c=g.get(o);return c||(c={localAgentId:i,inbound:createImInboundHandler({runtime:e.runtime,pluginConfig:e.pluginConfig,client:l.adapter,localServer:{getLocalAgentId:()=>i,resolveLocalAgentId:e=>e===s.id?i:void 0,getDefaultPlatformAgent:()=>({instanceId:t.instanceId}),ensureImInboundSession:(e,t,r,o)=>{a.ensureImInboundSession(e,t,r,o)},chatAbort:(e,t)=>a.chatAbort(e,t)},promptRunStore:sharedPromptRunStore,waitIfExclusive:(t,r)=>sharedImHotPathDeferral.waitIfExclusive(t,e.logger,r).then(()=>{}),assistantMessageCommitRouter:sharedAssistantMessageCommitRouter,toolResultObservationRouter:sharedToolResultObservationRouter,modelCallObservationRouter:sharedModelCallObservationRouter,sessionMutationCoordinator:n,logger:e.logger,writeObs:sharedWriteObs,principalIdOverride:t.instanceId,activeRunAuthority:a.getActiveRunAuthority(),applyTurnModel:(e,t)=>a.applyImTurnModel(e,t),restoreTurnModel:e=>a.restoreImTurnModel(e),...agentGateway?{completeA2ATask:(t,r,o)=>completeA2ATask({gateway:agentGateway,logger:e.logger},t,r,o)}:{}})},g.set(o,c)),c}})(t,i):void 0;if(!s)return void e.logger.warn?.(`[beeos-claw] native cloud chat dropped unresolvable target_agent_id=${i||"missing"} message_id=${r.id}`);("chat_cancel"===r.type?s.inbound.onChatCancel(r):s.inbound.onChatMessage(r)).catch(t=>{e.logger.error?.(`[beeos-claw] native cloud chat dispatch failed message_id=${r.id}: ${t instanceof Error?t.message:String(t)}`)})});try{await l.adapter.connect()}catch(e){throw u?.(),u=void 0,e}},disconnect:async()=>{u?.(),u=void 0,g.clear(),await l.adapter.disconnect()}}});return e.registerService({id:"beeos-native-cloud-chat",async start(){d.start()},async stop(){await d.stop()}}),e.logger.info?.("[beeos-claw] native Cloud personal-chat composition registered"),warmClaimAttached=!0,s&&d.start(),i}function adoptWarmClaim(e){const t=pluginCloudRuntimeTarget(e);if(!sharedRuntimeAuthority||!t)return;const r=sharedRuntimeAuthority.cloudTargetInstanceId;if(void 0===r)sharedRuntimeAuthority.bindCloudTarget(t);else if(r!==t)throw new Error("Cloud runtime authority target changed during process lifetime");if(void 0!==r||warmClaimAttached)return;let o;try{o=e.runtime?.config?.loadConfig?.()}catch{}attachNativeCloudChat(e,resolveConfigWithMeta({pluginConfig:e.pluginConfig??{},openclawConfig:o}).config)}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;adoptWarmClaim(e);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),registerManagedConnectorTools(e,agentGateway),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 a={current:null};installUnhandledRejectionObserver(e,o.writeObs,a),ensureRegisterToolCache(e),cachedCapabilityTools.length=0,r(o,a),agentGateway&&(e.on?e.on("before_agent_finalize",fileDeliveryFinalizeDecision):e.logger.warn?.("[file-delivery] OpenClaw plugin hooks unavailable; finalization check disabled")),registerServices(e,o,a),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
|
-
|
|
1
|
+
export const CONNECTOR_MCP_PROXY_PATH="/beeos/connectors/mcp";export const CONNECTOR_MCP_MAX_BODY_BYTES=262144;class RequestBodyTooLargeError extends Error{}export function isLoopbackAddress(e){return"127.0.0.1"===e||"::1"===e||"::ffff:127.0.0.1"===e}export function isLoopbackRequest(e){return isLoopbackAddress(e.socket.remoteAddress)}export function readBoundedRawBody(e,o=262144){return new Promise((r,t)=>{const n=[];let s=0,a=!1;const d=()=>{e.off("data",u),e.off("end",i),e.off("error",f),e.off("aborted",p)},c=e=>{a||(a=!0,d(),t(e))},u=r=>{const t=Buffer.isBuffer(r)?r:Buffer.from(r);if(s+=t.byteLength,s>o)return d(),e.resume(),void c(new RequestBodyTooLargeError("connector MCP request body is too large"));n.push(t)},i=()=>{a||(a=!0,d(),r(Buffer.concat(n,s)))},f=e=>c(e),p=()=>c(new Error("connector MCP request was aborted"));e.on("data",u),e.on("end",i),e.on("error",f),e.on("aborted",p)})}function writeTextResponse(e,o,r){e.statusCode=o,e.setHeader("Content-Type","text/plain; charset=utf-8"),e.end(r)}function copyRequestHeader(e,o,r){const t=e.headers[r.toLowerCase()];"string"==typeof t?o.set(r,t):Array.isArray(t)&&o.set(r,t.join(", "))}export async function handleConnectorMcpRequest(e,o,r){if(!isLoopbackRequest(e))return e.resume(),void writeTextResponse(o,403,"loopback access required");if("POST"!==e.method)return e.resume(),o.setHeader("Allow","POST"),void writeTextResponse(o,405,"method not allowed");if(e.url?.includes("?"))return e.resume(),void writeTextResponse(o,400,"query parameters are not supported");if(!r.gateway)return e.resume(),void writeTextResponse(o,503,"connector MCP proxy is not configured");let t;try{t=await readBoundedRawBody(e)}catch(e){return e instanceof RequestBodyTooLargeError?void writeTextResponse(o,413,"request body too large"):(r.logger?.warn?.(`[connector-mcp] failed to read request: ${String(e)}`),void(o.writableEnded||writeTextResponse(o,400,"invalid request body")))}const n=new Headers;copyRequestHeader(e,n,"Content-Type"),copyRequestHeader(e,n,"Accept"),copyRequestHeader(e,n,"MCP-Protocol-Version");try{const e=await r.gateway.connectors.mcp({method:"POST",headers:n,body:new Uint8Array(t)}),s=Buffer.from(await e.arrayBuffer());o.statusCode=e.status;const a=e.headers.get("content-type");a&&o.setHeader("Content-Type",a),o.end(s)}catch(e){r.logger?.warn?.(`[connector-mcp] upstream request failed: ${String(e)}`),o.writableEnded||writeTextResponse(o,502,"connector MCP upstream unavailable")}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AROUTER_PROVIDER_ID="arouter";export const DEFAULT_AROUTER_IMAGE_MODEL="gemini-2.5-flash-image";export const DEFAULT_AROUTER_VIDEO_MODEL="seedance-2.0-fast";const FALLBACK_AROUTER_BASE_URL="https://api.arouter.ai/v1";function trimTrailingSlash(
|
|
1
|
+
export const AROUTER_PROVIDER_ID="arouter";export const DEFAULT_AROUTER_IMAGE_MODEL="gemini-2.5-flash-image";export const DEFAULT_AROUTER_VIDEO_MODEL="seedance-2.0-fast";const FALLBACK_AROUTER_BASE_URL="https://api.arouter.ai/v1";function trimTrailingSlash(r){return r.replace(/\/+$/u,"")}const PLACEHOLDER_API_KEY=/^\$\{[^}]+\}$/u;function providersOf(r){return r?.models?.providers??{}}function hasProvider(r,e){return Object.prototype.hasOwnProperty.call(r,e)&&null!=r[e]}function listedModelIds(r){if(!r||!Array.isArray(r.models))return[];const e=[];for(const o of r.models){if("string"==typeof o){const r=o.trim();r&&e.push(r);continue}if(o&&"string"==typeof o.id){const r=o.id.trim();r&&e.push(r)}}return e}function providerListingModel(r,e){const o=Object.entries(r).filter(([,r])=>listedModelIds(r).includes(e));return 1===o.length?o[0]?.[0]:void 0}function soleProviderId(r){const e=Object.keys(r).filter(e=>hasProvider(r,e));return 1===e.length?e[0]:void 0}function providerFromRef(r,e){const o=e.indexOf("/");if(o<=0||o>=e.length-1)return;const t=e.slice(0,o).trim(),i=e.slice(o+1).trim();return t&&i?hasProvider(r,t)?t:providerListingModel(r,e)??providerListingModel(r,i):void 0}function resolveModelPointer(r,e){const o=e.trim();if(o)return o.includes("/")?providerFromRef(r,o):hasProvider(r,o)?o:providerListingModel(r,o)}function readToolModelRef(r,e){const o=r?.agents?.defaults?.[e];if("string"==typeof o){return o.trim()||void 0}if(o&&"string"==typeof o.primary){return o.primary.trim()||void 0}}export function resolveToolModelProviderId(r,e){const o=providersOf(r),t=e?.model?.trim();if(t){const r=resolveModelPointer(o,t);if(r)return r}const i=e?.toolModelField?readToolModelRef(r,e.toolModelField):void 0;if(i){const r=resolveModelPointer(o,i);if(r)return r}const n=e?.capabilityProviderId?.trim();return n&&hasProvider(o,n)?n:soleProviderId(o)}function providerIdFromHint(r,e){const o=e.trim();if(o)return resolveModelPointer(providersOf(r),o)}function readProviderApiKey(r,e){if(!e)return;const o=providersOf(r);if(!hasProvider(o,e))return;const t=o[e]?.apiKey;if("string"!=typeof t)return;const i=t.trim();return i&&!PLACEHOLDER_API_KEY.test(i)?i:void 0}export function resolveArouterApiKey(r,e){return readProviderApiKey(r,"string"==typeof e?providerIdFromHint(r,e):resolveToolModelProviderId(r,e))}export function resolveArouterBaseUrl(r){const e=r?.models?.providers?.arouter?.baseUrl?.trim();if(e)return trimTrailingSlash(e);const o=process.env.AROUTER_BASE_URL?.trim();return o?`${trimTrailingSlash(o)}/v1`:FALLBACK_AROUTER_BASE_URL}export function arouterAuthHeaders(r){return{Authorization:`Bearer ${r}`,"Content-Type":"application/json"}}const DEFAULT_REQUEST_TIMEOUT_MS=6e4;export async function arouterFetch(r,e={}){const o=e.timeoutMs??6e4,t=void 0!==e.deadlineAt?Math.max(0,e.deadlineAt-Date.now()):o,i=Math.max(1,Math.min(o,t)),n={method:e.method??"GET",signal:AbortSignal.timeout(i)};return e.headers&&(n.headers=e.headers),void 0!==e.body&&(n.body=e.body),fetch(r,n)}export async function readErrorBody(r){try{return(await r.text()).slice(0,500)}catch{return""}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AROUTER_PROVIDER_ID,DEFAULT_AROUTER_IMAGE_MODEL,arouterAuthHeaders,arouterFetch,readErrorBody,resolveArouterApiKey,resolveArouterBaseUrl}from"./arouter-config.js";const IMAGE_MODELS=[DEFAULT_AROUTER_IMAGE_MODEL],DEFAULT_IMAGE_TIMEOUT_MS=12e4,SUPPORTED_ASPECT_RATIOS=["1:1","2:3","3:2","3:4","4:3","4:5","5:4","9:16","16:9","21:9"],SUPPORTED_RESOLUTIONS=["1K","2K","4K"];function isRecord(e){return Boolean(e&&"object"==typeof e&&!Array.isArray(e))}function inferImageMimeType(e){return e.length>=8&&137===e[0]&&80===e[1]?"image/png":e.length>=3&&255===e[0]&&216===e[1]&&255===e[2]?"image/jpeg":e.length>=12&&"RIFF"===e.toString("ascii",0,4)&&"WEBP"===e.toString("ascii",8,12)?"image/webp":"image/png"}function toImageDataUrl(e){return`data:${e.mimeType};base64,${e.buffer.toString("base64")}`}function isGeminiImageModel(e){return/gemini/i.test(e)}function buildMessageContent(e){const t=e.inputImages??[];return 0===t.length?e.prompt:[{type:"text",text:e.prompt},...t.map(e=>({type:"image_url",image_url:{url:toImageDataUrl(e)}}))]}function buildImageConfig(e,t){if(!isGeminiImageModel(t))return{};const r={},o=e.aspectRatio?.trim();o&&(r.aspect_ratio=o);const a=e.resolution?.trim();return a&&(r.image_size=a),r}function decodeDataUrl(e){const t=/^data:([^;,]+)?(;base64)?,([\s\S]*)$/u.exec(e);if(!t)return null;const r=t[1]?.trim()||"image/png",o=Boolean(t[2]),a=t[3]??"",
|
|
1
|
+
import{AROUTER_PROVIDER_ID,DEFAULT_AROUTER_IMAGE_MODEL,arouterAuthHeaders,arouterFetch,readErrorBody,resolveArouterApiKey,resolveArouterBaseUrl}from"./arouter-config.js";const IMAGE_MODELS=[DEFAULT_AROUTER_IMAGE_MODEL],DEFAULT_IMAGE_TIMEOUT_MS=12e4,SUPPORTED_ASPECT_RATIOS=["1:1","2:3","3:2","3:4","4:3","4:5","5:4","9:16","16:9","21:9"],SUPPORTED_RESOLUTIONS=["1K","2K","4K"];function isRecord(e){return Boolean(e&&"object"==typeof e&&!Array.isArray(e))}function inferImageMimeType(e){return e.length>=8&&137===e[0]&&80===e[1]?"image/png":e.length>=3&&255===e[0]&&216===e[1]&&255===e[2]?"image/jpeg":e.length>=12&&"RIFF"===e.toString("ascii",0,4)&&"WEBP"===e.toString("ascii",8,12)?"image/webp":"image/png"}function toImageDataUrl(e){return`data:${e.mimeType};base64,${e.buffer.toString("base64")}`}function isGeminiImageModel(e){return/gemini/i.test(e)}function buildMessageContent(e){const t=e.inputImages??[];return 0===t.length?e.prompt:[{type:"text",text:e.prompt},...t.map(e=>({type:"image_url",image_url:{url:toImageDataUrl(e)}}))]}function buildImageConfig(e,t){if(!isGeminiImageModel(t))return{};const r={},o=e.aspectRatio?.trim();o&&(r.aspect_ratio=o);const a=e.resolution?.trim();return a&&(r.image_size=a),r}function decodeDataUrl(e){const t=/^data:([^;,]+)?(;base64)?,([\s\S]*)$/u.exec(e);if(!t)return null;const r=t[1]?.trim()||"image/png",o=Boolean(t[2]),a=t[3]??"",i=o?Buffer.from(a,"base64"):Buffer.from(decodeURIComponent(a),"utf8");return 0===i.length?null:{buffer:i,mimeType:r}}function collectImageUrls(e){const t=[];for(const r of e.choices??[]){const e=r?.message;if(!e)continue;for(const r of e.images??[]){const e=(r.image_url??r.imageUrl)?.url;"string"==typeof e&&e.length>0&&t.push(e)}const o=e.content;if("string"==typeof o&&o.length>0){const e=/data:image\/[^;]+;base64,[A-Za-z0-9+/=]+/gu;for(const r of o.matchAll(e))t.push(r[0])}else if(Array.isArray(o))for(const e of o)if(isRecord(e)&&"image_url"===e.type&&isRecord(e.image_url)){const r=e.image_url.url;"string"==typeof r&&r.length>0&&t.push(r)}}return t}async function assetFromUrl(e,t,r){let o,a=null;if(e.startsWith("data:")){const t=decodeDataUrl(e);t&&(a=t.buffer,o=t.mimeType)}else{const t=await arouterFetch(e,{deadlineAt:r});if(!t.ok)throw new Error(`ARouter image download failed (${t.status}): ${await readErrorBody(t)}`);a=Buffer.from(await t.arrayBuffer())}if(!a||0===a.length)return null;const i=o??inferImageMimeType(a);return{buffer:a,mimeType:i,fileName:`image-${t+1}.${"image/jpeg"===i?"jpg":"image/webp"===i?"webp":"png"}`}}export function createArouterImageProvider(){return{id:AROUTER_PROVIDER_ID,label:"ARouter Image",defaultModel:DEFAULT_AROUTER_IMAGE_MODEL,defaultTimeoutMs:12e4,models:IMAGE_MODELS,capabilities:{generate:{maxCount:1,supportsSize:!1,supportsAspectRatio:!0,supportsResolution:!0},edit:{enabled:!1},geometry:{aspectRatios:[...SUPPORTED_ASPECT_RATIOS],resolutions:[...SUPPORTED_RESOLUTIONS]}},isConfigured:e=>Boolean(resolveArouterApiKey(e.cfg,{toolModelField:"imageGenerationModel"})),async generateImage(e){const t=resolveArouterApiKey(e.cfg,{model:e.model,capabilityProviderId:e.provider,toolModelField:"imageGenerationModel"});if(!t)throw new Error("ARouter image generation: provider apiKey is not configured.");const r=resolveArouterBaseUrl(e.cfg),o=e.model?.trim()||DEFAULT_AROUTER_IMAGE_MODEL,a=Date.now()+(e.timeoutMs??12e4),i=buildImageConfig(e,o),n={model:o,messages:[{role:"user",content:buildMessageContent(e)}],modalities:["image","text"]},s=e.count&&e.count>1?Math.floor(e.count):1;s>1&&(n.n=s),Object.keys(i).length>0&&(n.image_config=i);const l=await arouterFetch(`${r}/chat/completions`,{method:"POST",headers:arouterAuthHeaders(t),body:JSON.stringify(n),deadlineAt:a});if(!l.ok)throw new Error(`ARouter image generation failed (${l.status}): ${await readErrorBody(l)}`);const u=await l.json(),g=collectImageUrls(u),m=[];for(let e=0;e<g.length;e+=1){const t=await assetFromUrl(g[e],e,a);t&&m.push(t)}if(0===m.length)throw new Error("ARouter image generation response missing image data.");return{images:m,model:o,...u.usage?{metadata:{usage:u.usage}}:{}}}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AROUTER_PROVIDER_ID,DEFAULT_AROUTER_VIDEO_MODEL,arouterAuthHeaders,arouterFetch,readErrorBody,resolveArouterApiKey,resolveArouterBaseUrl}from"./arouter-config.js";const VIDEO_MODELS=[DEFAULT_AROUTER_VIDEO_MODEL],DEFAULT_VIDEO_TIMEOUT_MS=3e5;export const AROUTER_VIDEO_POLL_INTERVAL_MS=2500;function sleep(e){return new Promise(
|
|
1
|
+
import{AROUTER_PROVIDER_ID,DEFAULT_AROUTER_VIDEO_MODEL,arouterAuthHeaders,arouterFetch,readErrorBody,resolveArouterApiKey,resolveArouterBaseUrl}from"./arouter-config.js";const VIDEO_MODELS=[DEFAULT_AROUTER_VIDEO_MODEL],DEFAULT_VIDEO_TIMEOUT_MS=3e5;export const AROUTER_VIDEO_POLL_INTERVAL_MS=2500;function sleep(e){return new Promise(o=>setTimeout(o,e))}function errorMessage(e){return"string"==typeof e.error?e.error:e.error&&"object"==typeof e.error&&e.error.message?e.error.message:`status=${e.status??"unknown"}`}function buildSubmitBody(e,o){const r={model:o,prompt:e.prompt,generate_audio:e.audio??!1};"number"==typeof e.durationSeconds&&Number.isFinite(e.durationSeconds)&&(r.duration=Math.max(1,Math.round(e.durationSeconds))),e.resolution?.trim()&&(r.resolution=e.resolution.trim()),e.aspectRatio?.trim()&&(r.aspect_ratio=e.aspectRatio.trim()),e.size?.trim()&&(r.size=e.size.trim());const t=(e.inputImages??[]).map(e=>e.url?.trim()).filter(e=>Boolean(e));if(t.length>0&&(r.frame_images=t),e.providerOptions)for(const[o,t]of Object.entries(e.providerOptions))void 0===t||o in r||(r[o]=t);return r}export async function pollArouterVideoTask(e){const o=`${e.baseUrl}/videos/${encodeURIComponent(e.taskId)}`,r=e.pollIntervalMs??2500;for(;;){if(Date.now()>=e.deadlineAt)throw new Error(`ARouter video task ${e.taskId} did not finish before timeout.`);const t=await arouterFetch(o,{headers:e.headers,deadlineAt:e.deadlineAt});if(!t.ok)throw new Error(`ARouter video poll failed (${t.status}): ${await readErrorBody(t)}`);const i=await t.json(),a=i.status?.toString().toLowerCase();if("completed"===a)return i;if("failed"===a||"cancelled"===a||"expired"===a)throw new Error(`ARouter video task ${e.taskId} ${a}: ${errorMessage(i)}`);await sleep(r)}}export function createArouterVideoProvider(){return{id:AROUTER_PROVIDER_ID,label:"ARouter Video",defaultModel:DEFAULT_AROUTER_VIDEO_MODEL,defaultTimeoutMs:3e5,models:VIDEO_MODELS,capabilities:{generate:{maxVideos:1,maxDurationSeconds:12,supportsResolution:!0,supportsAspectRatio:!0,supportsAudio:!0},imageToVideo:{enabled:!0,maxVideos:1,maxInputImages:1,maxDurationSeconds:12}},isConfigured:e=>Boolean(resolveArouterApiKey(e.cfg,{toolModelField:"videoGenerationModel"})),async generateVideo(e){const o=resolveArouterApiKey(e.cfg,{model:e.model,capabilityProviderId:e.provider,toolModelField:"videoGenerationModel"});if(!o)throw new Error("ARouter video generation: provider apiKey is not configured.");const r=resolveArouterBaseUrl(e.cfg),t=e.model?.trim()||DEFAULT_AROUTER_VIDEO_MODEL,i=arouterAuthHeaders(o),a=Date.now()+(e.timeoutMs??3e5),s=await arouterFetch(`${r}/videos`,{method:"POST",headers:i,body:JSON.stringify(buildSubmitBody(e,t)),deadlineAt:a});if(!s.ok)throw new Error(`ARouter video submit failed (${s.status}): ${await readErrorBody(s)}`);const d=await s.json(),n=d.id?.trim();if(!n)throw new Error("ARouter video submit response missing task id.");const u=await pollArouterVideoTask({baseUrl:r,taskId:n,headers:i,deadlineAt:a}),l=`${r}/videos/${encodeURIComponent(n)}/content?index=0`,m=await arouterFetch(l,{headers:i,deadlineAt:a});if(!m.ok)throw new Error(`ARouter video download failed (${m.status}): ${await readErrorBody(m)}`);return{videos:[{buffer:Buffer.from(await m.arrayBuffer()),mimeType:m.headers.get("content-type")?.trim()||"video/mp4",fileName:"video-1.mp4"}],model:t,metadata:{taskId:n,status:u.status,...u.generation_id?{generationId:u.generation_id}:{},...u.usage?{usage:u.usage}:{}}}}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createMessageClient}from"@beeos-ai/message-sdk";import{createNodeMessageClientComposition}from"@beeos-ai/message-sdk/node";export class BeeosClawMessageClientProcessOwner{composition;configurationKey;registrations=new Set;activeStop;startInFlight;stopInFlight;configure(t){const
|
|
1
|
+
import{createMessageClient}from"@beeos-ai/message-sdk";import{createNodeMessageClientComposition}from"@beeos-ai/message-sdk/node";import{createTokenProvider}from"@beeos-ai/message-sdk/auth";export function createBeeosClawMessageTokenProvider(t){return createTokenProvider(t)}export class BeeosClawMessageClientProcessOwner{composition;configurationKey;registrations=new Set;activeStop;startInFlight;stopInFlight;configure(t){const e=JSON.stringify({identityId:t.identityId,serviceUrl:t.serviceUrl??"",scopedDeliveryKey:t.runtimeDelivery?.scopedDeliveryKey??""});if(this.composition){if(this.configurationKey!==e)throw new Error("MessageClient process owner rejected incompatible hot-reload configuration");return this.composition}return this.configurationKey=e,this.composition=composeMessageClient(t),this.composition}createRegistrationToken(){return Symbol("beeos-claw-message-client-registration")}async acquire(t,e){if(this.registrations.has(t))this.startInFlight&&await this.startInFlight;else{if(!this.composition)throw new Error("MessageClient process owner is not configured");this.registrations.add(t);try{if(this.stopInFlight&&await this.stopInFlight,this.activeStop)return;this.startInFlight||(this.startInFlight=(async()=>{const t=await e(this.composition);this.activeStop=t})().finally(()=>{this.startInFlight=void 0})),await this.startInFlight}catch(e){throw this.registrations.delete(t),e}}}async release(t){if(this.registrations.delete(t)&&(this.startInFlight&&await this.startInFlight.catch(()=>{}),!(this.registrations.size>0)&&this.activeStop)){if(!this.stopInFlight){const t=this.activeStop;this.activeStop=void 0,this.stopInFlight=t().finally(()=>{this.stopInFlight=void 0})}await this.stopInFlight}}get referenceCount(){return this.registrations.size}get current(){return this.composition}}export const composeMessageClient=t=>{const e=createNodeMessageClientComposition(t);return{client:createMessageClient(e),nodeTransport:e.nodeTransport}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolveSyncAgentName}from"../agent-sync.js";import{AgentProjectionWorker,RuntimeProjectionTransportError}from"./agent-projection-worker.js";export class OpenClawAgentProjectionSource{getGateway;runtimeIds=new Map;constructor(t){this.getGateway=t}async listAgents(){const t=this.getGateway();if(!t?.isConnected)return{complete:!1,agents:[]};const e=await t.request("agents.list",{});return Array.isArray(e?.agents)?(this.runtimeIds.clear(),{complete:!0,agents:e.agents.map(t=>{const e=resolveSyncAgentName(t);return this.runtimeIds.set(e,t.id),{localKey:e,displayName:t.identity?.name||t.name||e,...t.description?{description:t.description}:{},...t.version?{version:t.version}:{},...t.identity?.avatarUrl?{avatarUrl:t.identity.avatarUrl}:{},...t.homepage?{homepage:t.homepage}:{},...t.defaultModel?{defaultModel:t.defaultModel}:{}}}).filter(t=>t.localKey)}):{complete:!1,agents:[]}}async listSkills(t){const e=this.getGateway();if(!e?.isConnected)return{complete:!1,skills:[]};try{const i=await e.request("skills.status",{agentId:this.runtimeIds.get(t)??t});return Array.isArray(i?.skills)?{complete:!0,skills:i.skills.filter(t=>!1!==t.eligible).map(t=>({skillKey:t.skillKey||t.name,name:t.name,...t.description?{description:t.description}:{},enabled:!t.disabled,...t.version?{version:t.version}:{}}))}:{complete:!1,skills:[]}}catch{return{complete:!1,skills:[]}}}}export class AgentGatewayHttpProjectionTransport{options;constructor(t){this.options=t}async apply(t,e){const i={runtimeEpoch:t.runtimeEpoch,revision:t.revision,snapshotId:t.snapshotId,canonicalHash:t.canonicalHash,agentsComplete:t.agentsComplete,skillsComplete:t.agents.every(t=>t.skillsComplete),agents:t.agents.map(t=>({runtimeAgentUid:t.runtimeAgentUid,localKey:t.localKey,displayName:t.displayName,...t.description?{description:t.description}:{},...t.version?{version:t.version}:{},...t.avatarUrl?{avatarUrl:t.avatarUrl}:{},...t.homepage?{homepage:t.homepage}:{},...t.defaultModel?{defaultModel:t.defaultModel}:{},capabilities:t.capabilities,skills:t.skills.map(t=>({skillKey:t.skillKey,name:t.name,...t.description?{description:t.description}:{},enabled:t.enabled,...t.version?{version:t.version}:{}})),skillsComplete:t.skillsComplete})),runtimeLeaseCredential:this.options.getRuntimeLeaseCredential(t)}
|
|
1
|
+
import{CloudHttpError}from"@beeos-ai/cloud-harness-sdk";import{resolveSyncAgentName}from"../agent-sync.js";import{AgentProjectionWorker,RuntimeProjectionTransportError}from"./agent-projection-worker.js";export class OpenClawAgentProjectionSource{getGateway;runtimeIds=new Map;constructor(t){this.getGateway=t}async listAgents(){const t=this.getGateway();if(!t?.isConnected)return{complete:!1,agents:[]};const e=await t.request("agents.list",{});return Array.isArray(e?.agents)?(this.runtimeIds.clear(),{complete:!0,agents:e.agents.map(t=>{const e=resolveSyncAgentName(t);return this.runtimeIds.set(e,t.id),{localKey:e,displayName:t.identity?.name||t.name||e,...t.description?{description:t.description}:{},...t.version?{version:t.version}:{},...t.identity?.avatarUrl?{avatarUrl:t.identity.avatarUrl}:{},...t.homepage?{homepage:t.homepage}:{},...t.defaultModel?{defaultModel:t.defaultModel}:{}}}).filter(t=>t.localKey)}):{complete:!1,agents:[]}}async listSkills(t){const e=this.getGateway();if(!e?.isConnected)return{complete:!1,skills:[]};try{const i=await e.request("skills.status",{agentId:this.runtimeIds.get(t)??t});return Array.isArray(i?.skills)?{complete:!0,skills:i.skills.filter(t=>!1!==t.eligible).map(t=>({skillKey:t.skillKey||t.name,name:t.name,...t.description?{description:t.description}:{},enabled:!t.disabled,...t.version?{version:t.version}:{}}))}:{complete:!1,skills:[]}}catch{return{complete:!1,skills:[]}}}}export class AgentGatewayHttpProjectionTransport{options;constructor(t){this.options=t}async apply(t,e){const i={runtimeEpoch:t.runtimeEpoch,revision:t.revision,snapshotId:t.snapshotId,canonicalHash:t.canonicalHash,agentsComplete:t.agentsComplete,skillsComplete:t.agents.every(t=>t.skillsComplete),agents:t.agents.map(t=>({runtimeAgentUid:t.runtimeAgentUid,localKey:t.localKey,displayName:t.displayName,...t.description?{description:t.description}:{},...t.version?{version:t.version}:{},...t.avatarUrl?{avatarUrl:t.avatarUrl}:{},...t.homepage?{homepage:t.homepage}:{},...t.defaultModel?{defaultModel:t.defaultModel}:{},capabilities:t.capabilities,skills:t.skills.map(t=>({skillKey:t.skillKey,name:t.name,...t.description?{description:t.description}:{},enabled:t.enabled,...t.version?{version:t.version}:{}})),skillsComplete:t.skillsComplete})),runtimeLeaseCredential:this.options.getRuntimeLeaseCredential(t)};let n;try{n=await this.options.gateway.agents.sync(i,{signal:e})}catch(t){if(!(t instanceof CloudHttpError))throw t;const e=t.transient,i=t.body.replace(/"runtimeLeaseCredential"\s*:\s*"[^"]*"/g,'"runtimeLeaseCredential":"<redacted>"').slice(0,512);throw new RuntimeProjectionTransportError(`Agent Gateway projection HTTP ${t.status}${i?`: ${i}`:""}`,e)}const r=n.acceptanceStatus,o=stringInteger(n.runtimeEpoch),a=stringInteger(n.revision);if(!o||!a||!["accepted","idempotent","stale_epoch","stale_revision","revision_hash_conflict"].includes(String(r)))throw new RuntimeProjectionTransportError("Agent Gateway returned malformed projection authority",!1);if("accepted"===r||"idempotent"===r){if(n.snapshotId!==t.snapshotId||n.canonicalHash!==t.canonicalHash||o!==t.runtimeEpoch||a!==t.revision)throw new RuntimeProjectionTransportError("Agent Gateway projection response correlation mismatch",!1);const e=validateAcceptedRows(n.data,t),i=e.map(t=>({runtimeAgentUid:t.runtimeAgentUid,platformAgentId:t.platformAgentId})),s=new Map;for(const t of e)s.set(t.runtimeLocalKey,{id:t.platformAgentId,instanceId:t.instanceId,name:t.runtimeLocalKey,displayName:String(t.raw.displayName??t.runtimeLocalKey),description:String(t.raw.description??""),version:String(t.raw.version??""),avatarUrl:String(t.raw.avatarUrl??""),status:String(t.raw.status??"active")});return this.options.onAccepted?.(s),{status:r,acceptedRuntimeEpoch:o,acceptedRevision:a,canonicalHash:String(n.canonicalHash),bindings:i}}return"revision_hash_conflict"===r?{status:r,acceptedRuntimeEpoch:o,acceptedRevision:a,acceptedCanonicalHash:String(n.canonicalHash??"")}:{status:r,acceptedRuntimeEpoch:o,acceptedRevision:a}}}const TEMPLATE_ORIGIN_REPORT_RETRY_LIMIT=3,TEMPLATE_ORIGIN_REPORT_RETRY_DELAY_MS=500;export class AgentGatewayTemplateOriginReporter{options;constructor(t){this.options=t}async report({platformAgentId:t,templateId:e}){let i;for(let n=1;n<=3;n++)try{return void await this.reportOnce(t,e)}catch(t){i=t,n<3&&await delay(this.options.retryDelayMs??500)}throw i instanceof Error?i:new Error(String(i))}async reportOnce(t,e){try{await this.options.gateway.agents.reportTemplateOrigin(t,e)}catch(t){if(!(t instanceof CloudHttpError))throw t;throw new Error(`Agent Gateway template-origin HTTP ${t.status}${t.body?`: ${t.body.slice(0,512)}`:""}`)}}}function delay(t){return new Promise(e=>setTimeout(e,t))}const TERMINAL_COMPACTION_RETRY_LIMIT=3,TERMINAL_COMPACTION_RETRY_DELAY_MS=250,TERMINAL_COMPACTION_BATCH_SIZE=32;export class AgentProjectionProduction{worker;unsubscribe;binding;transition=Promise.resolve();started=!1;terminalCompactionTimer;terminalCompactionRecovery;terminalCompactionAttempts=new Map;authority;journal;logger;constructor(t){this.authority=t.authority,this.journal=t.journal,this.logger=t.logger,this.worker=new AgentProjectionWorker({stateFile:t.stateFile,getLease:()=>t.authority.authorityLease,identities:t.identities,source:t.source,transport:t.transport,capabilities:t.capabilities,reconcileIntervalMs:t.reconcileIntervalMs,random:t.random,onBlocked:e=>t.logger?.warn?.(`[agent-projection] blocked: ${e}`),onReconciled:()=>this.onWorkerReconciled()})}async prepareCommittedMutation(t){return await this.worker.prepareCommittedMutation(t)}async applyCommittedMutation(t){return await this.worker.applyCommittedMutation(t)}async compactCommittedMutation(t){try{await this.worker.compactCommittedMutation(t),this.terminalCompactionAttempts.delete(t.operationId)}catch(t){throw this.scheduleTerminalCompactionRetry(),t}}start(){this.started||(this.started=!0,this.unsubscribe=this.authority.subscribeAuthority(t=>this.onAuthority(t)),this.onAuthority(this.authority.authorityLease),this.retryTerminalCompactions())}markDirty(){this.worker.markDirty()}onGatewayReconnect(){this.started&&this.authority.authorityLease&&(this.worker.reconcile("reconnect"),this.retryTerminalCompactions())}async stop(){this.started=!1,this.unsubscribe?.(),this.unsubscribe=void 0,this.terminalCompactionTimer&&clearTimeout(this.terminalCompactionTimer),this.terminalCompactionTimer=void 0,await this.queue(async()=>{this.binding=void 0,await this.worker.shutdown()})}onAuthority(t){const e=t?`${t.instanceId}\0${t.handlerIdentity}\0${t.runtimeEpoch}\0${t.leaseId}`:void 0;e!==this.binding&&(this.binding=e,this.queue(async()=>{await this.worker.shutdown(),this.started&&e&&e===this.binding&&this.worker.start()}))}queue(t){const e=this.transition.then(t,t);return this.transition=e.catch(()=>{}),e}onWorkerReconciled(){this.terminalCompactionAttempts.clear(),this.retryTerminalCompactions()}scheduleTerminalCompactionRetry(){this.started&&this.journal&&!this.terminalCompactionTimer&&(this.terminalCompactionTimer=setTimeout(()=>{this.terminalCompactionTimer=void 0,this.retryTerminalCompactions()},250))}async retryTerminalCompactions(){if(!this.started||!this.journal)return;if(this.terminalCompactionRecovery)return await this.terminalCompactionRecovery;const t=(async()=>{let t=!1;for(const e of(await this.worker.operationReferences()).slice(0,32)){const i=terminalIntentForReference(await this.journal.get(e.operationId),e);if(!i)continue;const n=this.terminalCompactionAttempts.get(e.operationId)??0;if(!(n>=3))try{await this.worker.compactCommittedMutation(i),this.terminalCompactionAttempts.delete(e.operationId)}catch(i){const r=n+1;this.terminalCompactionAttempts.set(e.operationId,r),this.logger?.warn?.(`[agent-projection] terminal reference compaction deferred (${r}/3): ${i instanceof Error?i.message:String(i)}`),t||=r<3}}t&&this.scheduleTerminalCompactionRetry()})();this.terminalCompactionRecovery=t;try{await t}finally{this.terminalCompactionRecovery===t&&(this.terminalCompactionRecovery=void 0)}}}function terminalIntentForReference(t,e){const i=t?.agentProjectionIntent;if(!i||i.operationId!==e.operationId||i.runtimeEpoch!==e.runtimeEpoch||i.projectionRevision!==e.projectionRevision||i.canonicalHash!==e.canonicalHash||i.snapshotRef!==e.snapshotRef)return;const n="projection_committed"===t.phase&&t.projectionReceipt?.revision===i.projectionRevision&&t.projectionReceipt.snapshot.revision===i.projectionRevision,r="blocked"===t.agentProjectionTerminal?.state&&t.agentProjectionTerminal.revision===i.projectionRevision;return n||r?i:void 0}function stringInteger(t){return"string"==typeof t&&/^(0|[1-9][0-9]*)$/.test(t)?t:Number.isSafeInteger(t)&&t>=0?String(t):null}const nonEmpty=t=>"string"==typeof t&&t.length>0?t:null;function validateAcceptedRows(t,e){if(!Array.isArray(t)||t.length!==e.agents.length)throw new RuntimeProjectionTransportError("Agent Gateway projection row count mismatch",!1);const i=new Map(e.agents.map(t=>[t.runtimeAgentUid,t.localKey])),n=new Set,r=new Set,o=new Set,a=t.map(t=>{if(!t||"object"!=typeof t||Array.isArray(t))throw new RuntimeProjectionTransportError("Agent Gateway projection row is malformed",!1);const a=t,s=nonEmpty(a.runtimeAgentUid),c=nonEmpty(a.runtimeLocalKey),l=nonEmpty(a.id),p=nonEmpty(a.instanceId);if(!s||!c||!l||!p||p!==e.instanceId||i.get(s)!==c||n.has(s)||r.has(c)||o.has(l))throw new RuntimeProjectionTransportError("Agent Gateway projection identity binding mismatch",!1);return n.add(s),r.add(c),o.add(l),{raw:a,runtimeAgentUid:s,runtimeLocalKey:c,platformAgentId:l,instanceId:p}});if(n.size!==i.size)throw new RuntimeProjectionTransportError("Agent Gateway projection omitted identity binding",!1);return a}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export class SerializedCallbackQueue{pending=[];idleWaiters=[];running=!1;failure;enqueueSync(i){void 0===this.failure&&(this.pending.push({run:i}),this.running||this.pump())}waitForIdle(){return void 0!==this.failure?Promise.reject(this.failure):this.running||0!==this.pending.length?new Promise((i,e)=>{this.idleWaiters.push({resolve:i,reject:e})}):Promise.resolve()}fail(i){for(void 0===this.failure&&(this.failure=i),this.running=!1,this.pending=[];this.idleWaiters.length>0;){this.idleWaiters.shift().reject(this.failure)}}pendingCount(){return this.pending.length}isFailed(){return void 0!==this.failure}pump(){if(!this.running&&void 0===this.failure){for(;this.pending.length>0;){const i=this.pending.shift();this.running=!0;try{i.run(),this.running=!1}catch(i){return this.running=!1,void this.fail(i)}}this.resolveIdle()}}resolveIdle(){if(!(this.running||this.pending.length>0||void 0!==this.failure))for(;this.idleWaiters.length>0;){this.idleWaiters.shift().resolve()}}}
|
|
1
|
+
export class SerializedCallbackQueue{pending=[];idleWaiters=[];running=!1;failure;enqueueSync(i){return void 0===this.failure&&(this.pending.push({run:i}),this.running||this.pump(),!0)}waitForIdle(){return void 0!==this.failure?Promise.reject(this.failure):this.running||0!==this.pending.length?new Promise((i,e)=>{this.idleWaiters.push({resolve:i,reject:e})}):Promise.resolve()}fail(i){for(void 0===this.failure&&(this.failure=i),this.running=!1,this.pending=[];this.idleWaiters.length>0;){this.idleWaiters.shift().reject(this.failure)}}pendingCount(){return this.pending.length}isFailed(){return void 0!==this.failure}pump(){if(!this.running&&void 0===this.failure){for(;this.pending.length>0;){const i=this.pending.shift();this.running=!0;try{i.run(),this.running=!1}catch(i){return this.running=!1,void this.fail(i)}}this.resolveIdle()}}resolveIdle(){if(!(this.running||this.pending.length>0||void 0!==this.failure))for(;this.idleWaiters.length>0;){this.idleWaiters.shift().resolve()}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID}from"node:crypto";const TITLE_SYSTEM_PROMPT_BASE='You are a conversation title generator. Your task is to generate a concise, human-readable title summarizing the topic of the user\'s question together with the assistant\'s answer.\n\n### Rules:\n- Length: 3-6 words in English, or 6-20 characters in Chinese/Japanese/Korean/Thai (up to 24 if needed to keep all key domain terms intact).\n- Language: When a Client UI locale is provided below, write the title in THAT language even if the user wrote in a different language (translate the topic). Otherwise match the user\'s input language exactly. Mixed zh/en input → use the dominant language. Do NOT switch languages away from the required locale.\n- Extract the core topic (noun-centric) of the Q&A exchange, not the action verb.\n- Use the assistant\'s answer to disambiguate or enrich the topic when the question alone is vague (e.g. "帮我看下" + an answer about x402 → "x402 支付集成").\n- No punctuation, no quotation marks, no emojis, no markdown.\n- No prefix like "Title:" or "Here is". Output the title only.\n- Avoid generic words: "help", "question", "chat", "problem", "task".\n- Greetings and self-introductions ARE concrete topics — never treat them as vague. Prefer the locale-native self-intro title from the Client UI locale section when present.\n- NEVER return placeholder / empty-chat titles such as "新会话", "新對話", "New chat", "New Conversation", "新しいチャット", "새 채팅", "แชตใหม่". Always invent a concrete noun-centric topic from whatever words are present.\n\n### Input Format:\nThe user message will contain both the question and the assistant\'s answer, delimited like this:\n[User Question]\n...question text...\n\n[Assistant Answer]\n...answer text (may be truncated with "..." in the middle)...\n\n### Output Format:\nRespond ONLY with valid JSON, no other text:\n{"title": "<your title here>"}\n\n### Examples:\nInput:\n[User Question]\n帮我写一个关于BeeOS设备接入的PRD\n\n[Assistant Answer]\n好的,这是 BeeOS 设备接入 PRD 的草稿:1. 目标 ...\nOutput: {"title": "BeeOS 设备接入 PRD"}\n\nInput:\n[User Question]\n帮我看下\n\n[Assistant Answer]\n你说的 x402 支付协议是一个基于 HTTP 402 的链上支付标准 ...\nOutput: {"title": "x402 支付协议解析"}\n\nInput:\n[User Question]\nWhat\'s the best way to integrate x402 payment protocol?\n\n[Assistant Answer]\nYou have three options: 1. Use the official SDK ...\nOutput: {"title": "x402 Payment Integration"}\n\nInput:\n[User Question]\n用一句话介绍一下你自己。\n\n[Assistant Answer]\n我是 BeeOS 智能助手,可以帮助你完成设备控制与任务协作。\nOutput: {"title": "自我介绍"}\n\nInput:\n[User Question]\nhi\n\n[Assistant Answer]\nHello! How can I help you today?\nOutput: {"title": "Greeting"}',SELF_INTRO_BY_LOCALE={zh:"自我介绍","zh-TW":"自我介紹",ja:"自己紹介",ko:"자기소개",th:"แนะนำตัว",en:"Self Introduction"},SELF_INTRO_ALIASES=new Set(Object.values(SELF_INTRO_BY_LOCALE).map(e=>e.toLowerCase())),LOCALE_PROMPT_HINT={zh:'zh (简体中文) — write the title in Simplified Chinese. Self-intro → "自我介绍".',"zh-TW":'zh-TW (繁體中文) — write the title in Traditional Chinese. Self-intro → "自我介紹".',ja:'ja (日本語) — write the title in Japanese. Self-intro → "自己紹介". Never use Chinese "自我介绍".',ko:'ko (한국어) — write the title in Korean. Self-intro → "자기소개".',th:'th (ไทย) — write the title in Thai. Self-intro → "แนะนำตัว".',en:'en (English) — write the title in English. Self-intro → "Self Introduction".'},TITLE_TEMPLATES=[{match:["今日日报","日报"],zh:"今日工作日报",en:"Daily Work Log"},{match:["周报","周报总结","本周周报"],zh:"本周工作周报",en:"Weekly Work Report"},{match:["月报","月度汇报","月度总结"],zh:"本月工作月报",en:"Monthly Work Report"},{match:["工作日志","日志"],zh:"工作日志整理",en:"Work Log Review"},{match:["晨会","今日晨会"],zh:"今日晨会纪要",en:"Daily Standup Notes"},{match:["复盘","今日复盘"],zh:"今日工作复盘",en:"Daily Retrospective"}],PLACEHOLDER_TITLES=new Set(["new chat","new conversation","新会话","新對話","新しいチャット","새 채팅","แชตใหม่"]),PLACEHOLDER_TO_LOCALE={"new chat":"en","new conversation":"en","新会话":"zh","新對話":"zh-TW","新しいチャット":"ja","새 채팅":"ko","แชตใหม่":"th"};export function inferTitleLocaleFromPlaceholder(e){if(!e)return;const t=e.trim().toLowerCase();return PLACEHOLDER_TO_LOCALE[t]??PLACEHOLDER_TO_LOCALE[e.trim()]}export function buildTitleSystemPrompt(e){return e?`${TITLE_SYSTEM_PROMPT_BASE}\n\n### Client UI locale\n${LOCALE_PROMPT_HINT[e]}\nCRITICAL: The title language MUST match this locale, even when [User Question] is in another language.`:TITLE_SYSTEM_PROMPT_BASE}export function alignTitleWithLocale(e,t){return t&&SELF_INTRO_ALIASES.has(e.trim().toLowerCase())?SELF_INTRO_BY_LOCALE[t]:e}export function isPlaceholderTitle(e){if(!e)return!0;const t=e.trim();return!t||(!!PLACEHOLDER_TITLES.has(t.toLowerCase())||(!!/^[0-9a-f]{6,12}\s*\(20\d{2}/i.test(t)||(!!/^Sender\s*\(untrusted/i.test(t)||!!/^Conversation\s+info\s*\(untrusted/i.test(t))))}export function isGuardMessage(e){const t=e.trim();return[...t].length<3||[...t].every(e=>/[\p{P}\p{S}\s]/u.test(e))}export function matchTitleTemplate(e){const t=e.trim().toLowerCase();for(const n of TITLE_TEMPLATES)if(n.match.some(e=>e.toLowerCase()===t))return/[\u4e00-\u9fff]/.test(e)?n.zh:n.en}function truncateQuestionForTitle(e){return e.length>2e3?e.slice(0,1500):e}function truncateAnswerForTitle(e){return e.length<=1e3?e:`${e.slice(0,500)}\n...\n${e.slice(-500)}`}export function fallbackTitleFromQuestion(e){const t=e.replace(/[\r\n\t]+/g," ").replace(/[。!?.!?…]+$/u,"").trim();if(!t||isGuardMessage(t)||isPlaceholderTitle(t))return;const n=[...t];return n.length<=20?t:n.slice(0,18).join("")}export async function generateTitleFromQA(e,t,n,i="title-gen"){let o,r,a=i;if(n&&("locale"in n||"logPrefix"in n||"logger"in n)){const e=n;o=e.logger,a=e.logPrefix??"title-gen",r=e.locale}else o=n;if(isGuardMessage(e))return void o?.info?.(`[${a}] SKIP guard message`);const s=matchTitleTemplate(e);if(s){const e=alignTitleWithLocale(s,r);return o?.info?.(`[${a}] template title="${e}"`),e}const l=(process.env.AROUTER_BASE_URL||"").replace(/\/$/,""),c=process.env.AROUTER_API_KEY||"";if(!l||!c)return void o?.info?.(`[${a}] SKIP: no AROUTER env vars`);const u=`[User Question]\n${truncateQuestionForTitle(e)}\n\n[Assistant Answer]\n${truncateAnswerForTitle(t)}`;o?.info?.(`[${a}] CALLING LLM q="${e.slice(0,60)}" aLen=${t.length}${r?` locale=${r}`:""}`);try{const t=await fetch(`${l}/v1/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify({model:"openai/gpt-4o-mini",max_tokens:32,temperature:.3,messages:[{role:"system",content:buildTitleSystemPrompt(r)},{role:"user",content:u}]})});if(!t.ok){const e=await t.text().catch(()=>"");return void o?.info?.(`[${a}] FAILED status=${t.status} body=${e.slice(0,300)}`)}const n=await t.json(),i=n.choices?.[0]?.message?.content?.trim();if(!i)return;const s=i.replace(/^```json\s*/,"").replace(/```$/,"").trim();let h;try{h=JSON.parse(s).title?.trim()??""}catch{return void o?.debug?.(`[${a}] JSON parse failed: ${s}`)}if(!h||isPlaceholderTitle(h)){const t=fallbackTitleFromQuestion(e);if(t){const n=alignTitleWithLocale(t,r),i=r&&n===t&&/介绍一下你自己|介紹一下你自己|introduce yourself|自己紹介|자기소개/i.test(e)?SELF_INTRO_BY_LOCALE[r]:n;return o?.info?.(`[${a}] discarded placeholder/empty title="${h}"; fallback="${i}"`),i}return void o?.info?.(`[${a}] discarded placeholder/empty title="${h}"`)}const
|
|
1
|
+
import{randomUUID}from"node:crypto";const TITLE_SYSTEM_PROMPT_BASE='You are a conversation title generator. Your task is to generate a concise, human-readable title summarizing the topic of the user\'s question together with the assistant\'s answer.\n\n### Rules:\n- Length: 3-6 words in English, or 6-20 characters in Chinese/Japanese/Korean/Thai (up to 24 if needed to keep all key domain terms intact).\n- Language: When a Client UI locale is provided below, write the title in THAT language even if the user wrote in a different language (translate the topic). Otherwise match the user\'s input language exactly. Mixed zh/en input → use the dominant language. Do NOT switch languages away from the required locale.\n- Extract the core topic (noun-centric) of the Q&A exchange, not the action verb.\n- Use the assistant\'s answer to disambiguate or enrich the topic when the question alone is vague (e.g. "帮我看下" + an answer about x402 → "x402 支付集成").\n- No punctuation, no quotation marks, no emojis, no markdown.\n- No prefix like "Title:" or "Here is". Output the title only.\n- Avoid generic words: "help", "question", "chat", "problem", "task".\n- Greetings and self-introductions ARE concrete topics — never treat them as vague. Prefer the locale-native self-intro title from the Client UI locale section when present.\n- NEVER return placeholder / empty-chat titles such as "新会话", "新對話", "New chat", "New Conversation", "新しいチャット", "새 채팅", "แชตใหม่". Always invent a concrete noun-centric topic from whatever words are present.\n\n### Input Format:\nThe user message will contain both the question and the assistant\'s answer, delimited like this:\n[User Question]\n...question text...\n\n[Assistant Answer]\n...answer text (may be truncated with "..." in the middle)...\n\n### Output Format:\nRespond ONLY with valid JSON, no other text:\n{"title": "<your title here>"}\n\n### Examples:\nInput:\n[User Question]\n帮我写一个关于BeeOS设备接入的PRD\n\n[Assistant Answer]\n好的,这是 BeeOS 设备接入 PRD 的草稿:1. 目标 ...\nOutput: {"title": "BeeOS 设备接入 PRD"}\n\nInput:\n[User Question]\n帮我看下\n\n[Assistant Answer]\n你说的 x402 支付协议是一个基于 HTTP 402 的链上支付标准 ...\nOutput: {"title": "x402 支付协议解析"}\n\nInput:\n[User Question]\nWhat\'s the best way to integrate x402 payment protocol?\n\n[Assistant Answer]\nYou have three options: 1. Use the official SDK ...\nOutput: {"title": "x402 Payment Integration"}\n\nInput:\n[User Question]\n用一句话介绍一下你自己。\n\n[Assistant Answer]\n我是 BeeOS 智能助手,可以帮助你完成设备控制与任务协作。\nOutput: {"title": "自我介绍"}\n\nInput:\n[User Question]\nhi\n\n[Assistant Answer]\nHello! How can I help you today?\nOutput: {"title": "Greeting"}',SELF_INTRO_BY_LOCALE={zh:"自我介绍","zh-TW":"自我介紹",ja:"自己紹介",ko:"자기소개",th:"แนะนำตัว",en:"Self Introduction"},SELF_INTRO_ALIASES=new Set(Object.values(SELF_INTRO_BY_LOCALE).map(e=>e.toLowerCase())),LOCALE_PROMPT_HINT={zh:'zh (简体中文) — write the title in Simplified Chinese. Self-intro → "自我介绍".',"zh-TW":'zh-TW (繁體中文) — write the title in Traditional Chinese. Self-intro → "自我介紹".',ja:'ja (日本語) — write the title in Japanese. Self-intro → "自己紹介". Never use Chinese "自我介绍".',ko:'ko (한국어) — write the title in Korean. Self-intro → "자기소개".',th:'th (ไทย) — write the title in Thai. Self-intro → "แนะนำตัว".',en:'en (English) — write the title in English. Self-intro → "Self Introduction".'},TITLE_TEMPLATES=[{match:["今日日报","日报"],zh:"今日工作日报",en:"Daily Work Log"},{match:["周报","周报总结","本周周报"],zh:"本周工作周报",en:"Weekly Work Report"},{match:["月报","月度汇报","月度总结"],zh:"本月工作月报",en:"Monthly Work Report"},{match:["工作日志","日志"],zh:"工作日志整理",en:"Work Log Review"},{match:["晨会","今日晨会"],zh:"今日晨会纪要",en:"Daily Standup Notes"},{match:["复盘","今日复盘"],zh:"今日工作复盘",en:"Daily Retrospective"}],PLACEHOLDER_TITLES=new Set(["new chat","new conversation","新会话","新對話","新しいチャット","새 채팅","แชตใหม่"]),PLACEHOLDER_TO_LOCALE={"new chat":"en","new conversation":"en","新会话":"zh","新對話":"zh-TW","新しいチャット":"ja","새 채팅":"ko","แชตใหม่":"th"};export function inferTitleLocaleFromPlaceholder(e){if(!e)return;const t=e.trim().toLowerCase();return PLACEHOLDER_TO_LOCALE[t]??PLACEHOLDER_TO_LOCALE[e.trim()]}export function buildTitleSystemPrompt(e){return e?`${TITLE_SYSTEM_PROMPT_BASE}\n\n### Client UI locale\n${LOCALE_PROMPT_HINT[e]}\nCRITICAL: The title language MUST match this locale, even when [User Question] is in another language.`:TITLE_SYSTEM_PROMPT_BASE}export function alignTitleWithLocale(e,t){return t&&SELF_INTRO_ALIASES.has(e.trim().toLowerCase())?SELF_INTRO_BY_LOCALE[t]:e}export function isPlaceholderTitle(e){if(!e)return!0;const t=e.trim();return!t||(!!PLACEHOLDER_TITLES.has(t.toLowerCase())||(!!/^[0-9a-f]{6,12}\s*\(20\d{2}/i.test(t)||(!!/^Sender\s*\(untrusted/i.test(t)||!!/^Conversation\s+info\s*\(untrusted/i.test(t))))}export function isGuardMessage(e){const t=e.trim();return[...t].length<3||[...t].every(e=>/[\p{P}\p{S}\s]/u.test(e))}export function matchTitleTemplate(e){const t=e.trim().toLowerCase();for(const n of TITLE_TEMPLATES)if(n.match.some(e=>e.toLowerCase()===t))return/[\u4e00-\u9fff]/.test(e)?n.zh:n.en}function truncateQuestionForTitle(e){return e.length>2e3?e.slice(0,1500):e}function truncateAnswerForTitle(e){return e.length<=1e3?e:`${e.slice(0,500)}\n...\n${e.slice(-500)}`}export function fallbackTitleFromQuestion(e){const t=e.replace(/[\r\n\t]+/g," ").replace(/[。!?.!?…]+$/u,"").trim();if(!t||isGuardMessage(t)||isPlaceholderTitle(t))return;const n=[...t];return n.length<=20?t:n.slice(0,18).join("")}export async function generateTitleFromQA(e,t,n,i="title-gen"){let o,r,a=i;if(n&&("locale"in n||"logPrefix"in n||"logger"in n)){const e=n;o=e.logger,a=e.logPrefix??"title-gen",r=e.locale}else o=n;if(isGuardMessage(e))return void o?.info?.(`[${a}] SKIP guard message`);const s=matchTitleTemplate(e);if(s){const e=alignTitleWithLocale(s,r);return o?.info?.(`[${a}] template title="${e}"`),e}const l=(process.env.AROUTER_BASE_URL||"").replace(/\/$/,""),c=process.env.AROUTER_API_KEY||"";if(!l||!c)return void o?.info?.(`[${a}] SKIP: no AROUTER env vars`);const u=`[User Question]\n${truncateQuestionForTitle(e)}\n\n[Assistant Answer]\n${truncateAnswerForTitle(t)}`;o?.info?.(`[${a}] CALLING LLM q="${e.slice(0,60)}" aLen=${t.length}${r?` locale=${r}`:""}`);try{const t=await fetch(`${l}/v1/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify({model:"openai/gpt-4o-mini",max_tokens:32,temperature:.3,messages:[{role:"system",content:buildTitleSystemPrompt(r)},{role:"user",content:u}]})});if(!t.ok){const e=await t.text().catch(()=>"");return void o?.info?.(`[${a}] FAILED status=${t.status} body=${e.slice(0,300)}`)}const n=await t.json(),i=n.choices?.[0]?.message?.content?.trim();if(!i)return;const s=i.replace(/^```json\s*/,"").replace(/```$/,"").trim();let h;try{h=JSON.parse(s).title?.trim()??""}catch{return void o?.debug?.(`[${a}] JSON parse failed: ${s}`)}if(!h||isPlaceholderTitle(h)){const t=fallbackTitleFromQuestion(e);if(t){const n=alignTitleWithLocale(t,r),i=r&&n===t&&/介绍一下你自己|介紹一下你自己|introduce yourself|自己紹介|자기소개/i.test(e)?SELF_INTRO_BY_LOCALE[r]:n;return o?.info?.(`[${a}] discarded placeholder/empty title="${h}"; fallback="${i}"`),i}return void o?.info?.(`[${a}] discarded placeholder/empty title="${h}"`)}const d=alignTitleWithLocale(h,r);return o?.info?.(d!==h?`[${a}] OK title="${h}" → locale-aligned="${d}"`:`[${a}] OK title="${h}"`),d}catch(e){return void o?.info?.(`[${a}] ERROR: ${e instanceof Error?e.message:e}`)}}export function createConversationTitleRenameIntent(e,t){return Object.freeze({conversationId:e,title:t,commandId:randomUUID()})}export async function patchMsConversationTitle(e,t){const n=e.conversations;if(!n)throw new Error("conversation title administration is unavailable");await n.update({conversationId:t.conversationId,title:t.title,idempotencyKey:t.commandId})}export async function maybeRenameImConversationTitle(e){const{client:t,conversationId:n,question:i,answer:o,logger:r}=e,a=`im-title-gen conv=${n}`;if(!n||!i.trim()||!o.trim())return void r?.debug?.(`[${a}] SKIP missing conversation/q/a`);const s=t.conversations;if(!s)return void r?.debug?.(`[${a}] SKIP conversation admin unavailable`);let l;try{l=(await s.get(n)).title}catch(e){return void r?.info?.(`[${a}] GET conversation failed: ${e instanceof Error?e.message:e}`)}if(!isPlaceholderTitle(l))return void r?.debug?.(`[${a}] SKIP non-placeholder title="${l}"`);const c=inferTitleLocaleFromPlaceholder(l),u=await generateTitleFromQA(i,o,{logger:r,logPrefix:a,locale:c});if(!u)return;const h=createConversationTitleRenameIntent(n,u);try{return await patchMsConversationTitle(t,h),r?.info?.(`[${a}] PATCH MS title OK title="${u}"`),u}catch(e){return void r?.info?.(`[${a}] PATCH MS title FAILED: ${e instanceof Error?e.message:e}`)}}
|