beeos-claw 0.6.93 → 0.6.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import{createHash}from"node:crypto";import{isDeepStrictEqual}from"node:util";import{ChatStoreHttpError,chatAppendDigest,decodeNativeChatEvent,encodeNativeChatEvent}from"@beeos-ai/cloud-harness-sdk";import{OPENCLAW_NATIVE_CODEC,assertCentralNativeReceipt,nativePayloadDigest}from"./central-native-context-engine.js";import{generatedSessionName}from"./central-native-titles.js";const codec={name:"openclaw-session-events",version:"1"};export const CENTRAL_RESPONSE_CONTROL_CODEC={name:"beeos-response-control",version:"1"};const executionObservationType="response.beeos.execution_observation",decimal=e=>"string"==typeof e&&/^(0|[1-9][0-9]*)$/.test(e),key=e=>JSON.stringify([e.context.tenant_ref,e.context.scope_ref,e.sessionId,e.historyGeneration,e.branchId]),operationKey=e=>JSON.stringify([key(e),e.operationId,e.responseId,e.attemptId]),object=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),publicId=e=>"string"==typeof e&&/^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/.test(e)?e:null;export function publicModelRoute(e,t){if("string"==typeof e&&e.includes("/")){const t=e.indexOf("/");return[publicId(e.slice(0,t)),publicId(e.slice(t+1))]}return[publicId(t),publicId(e)]}function executedRoute(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.terminalReceipt)?t.terminalReceipt:{},i=object(n.effective)?n.effective:{},r=object(e.meta.executionTrace)?e.meta.executionTrace:{};return"string"==typeof i.responseModel?i.responseModel:"string"==typeof r.winnerModel?r.winnerModel:i.model}export function publicModelId(e){if("string"==typeof e&&0!==e.length)return publicId(e.includes("/")?`arouter_${e.replaceAll("/","_")}`:e)??void 0}function executedFacts(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.terminalReceipt)?t.terminalReceipt:{},i=object(n.effective)?n.effective:{},r=object(e.meta.executionTrace)?e.meta.executionTrace:{},o=object(e.meta.requestShaping)?e.meta.requestShaping:{},a="string"==typeof n.runId?n.runId:void 0,[s,d]=publicModelRoute(executedRoute(e),"string"==typeof i.provider?i.provider:r.winnerProvider);if(a&&s&&d)return{nativeRunId:a,facts:{actual_provider_id:s,actual_model_id:d,..."boolean"==typeof r.fallbackUsed?{fallback_used:r.fallbackUsed}:{},..."string"==typeof o.reasoning?{reasoning:o.reasoning}:{}}}}function terminalOutputItem(e){const t="string"==typeof e.toolCallId?e.toolCallId:"string"==typeof e.tool_call_id?e.tool_call_id:void 0,n="string"==typeof e.toolName?e.toolName:"string"==typeof e.tool_name?e.tool_name:void 0;if(t||n){if(!t||!n)throw new Error("native tool result lacks its tool call identity");return{type:"tool_summary",tool_call_id:t,tool_name:n,outcome:!0===e.isError?"failed":!1===e.isError?"succeeded":"unknown",summary:"string"==typeof e.text?e.text.slice(0,4096):""}}return"string"==typeof e.text&&e.text.length>0?{type:"output_text",text:e.text}:void 0}function terminalUsage(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.usage)?t.usage:void 0;if(!n)return;const i=e=>"number"==typeof e&&Number.isSafeInteger(e)&&e>=0?e:void 0,r=i(n.input),o=i(n.output);if(void 0===r&&void 0===o)return;const a=publicModelId(executedRoute(e));return{input_tokens:r??0,output_tokens:o??0,source:"provider",...a?{actual_model_id:a}:{}}}function terminalProjection(e,t){const n=t.outcome,i=["cancelled","aborted","superseded"].includes(n.reason)?"cancelled":["hard_timeout","timed_out","abandoned"].includes(n.reason)||["max_tokens","length","max_output_tokens"].includes(n.stopReason??"")?"incomplete":"completed"===n.reason&&"ok"===n.status?"completed":"failed",r=[];for(const e of t.payloads){if(!object(e))throw new Error("native terminal payload is not a typed reply");if(e.mediaUrl||Array.isArray(e.mediaUrls)&&e.mediaUrls.length>0)throw new Error("native media output requires its authorized central file projection");const t=terminalOutputItem(e);t&&r.push(t)}const o=object(t.meta.agentMeta)?t.meta.agentMeta:{},a=terminalUsage(t);return{status:i,event:{type:"cancelled"===i?"response.failed":`response.${i}`,response:{id:e.responseId,status:i,output:r,..."string"==typeof o.model&&o.model.length>0?{model:o.model}:{},...a?{usage:a}:{},error:"failed"===i?{type:"harness_error",code:"harness_error",message:n.error||"The native harness could not complete this response."}:null,incomplete_details:"incomplete"===i?{reason:"completed"===n.reason?"max_output_tokens":"runtime_interrupted"}:null}}}}export class StateCentralNativeStore{client;credential;titles;writes=new Map;heads=new Map;publicEvents=new Map;memoryReads=new Map;executionObservations=new Map;constructor(e,t,n){this.client=e,this.credential=t,this.titles=n}async recordGeneratedTitle(e,t){if(!this.titles)throw new Error("generated Session titles are unavailable");const n=generatedSessionName(t);if(!n)throw new Error("generated Session title is empty");return await this.titles.title(await this.credential(e),{context:e.context,session_id:e.sessionId,history_generation:e.historyGeneration,branch_id:e.branchId,name:n,idempotency_key:`title:${e.operationId}`})}withWrite(e,t){const n=key(e),i=(this.writes.get(n)??Promise.resolve()).then(t);return this.writes.set(n,i),i}async commitPublicProgress(e,t){await this.withWrite(e,async()=>{if(!this.publicEvents.get(operationKey(e))?.length)return;if(0!==(await t.list(e.sessionId)).length)throw new Error("native progress has unresolved original writes");const n=await this.load(e);if(n.terminal?.response_id===e.responseId)throw new Error("original native Response is already terminal");const i=structuredClone(this.publicEvents.get(operationKey(e))??[]),r=nativePayloadDigest(i),o=this.prepareAppend({binding:e,events:[],expectedWatermark:n.watermark,publicProgress:!0,idempotencyKey:`progress:${e.operationId}:${n.watermark}:${r}`,nativeSnapshotDigest:r});await t.put(o);const a=await this.append(o);assertCentralNativeReceipt(o,a),await t.complete(o,a)})}recordPublicEvent(e,t){const n=operationKey(e),i=this.publicEvents.get(n)??[];i.push(structuredClone(t)),this.publicEvents.set(n,i)}recordMemoryRead(e,t){if("read"===t.status&&!t.watermark)throw new Error("actual Memory recall omitted its read watermark");this.memoryReads.set(operationKey(e),structuredClone(t))}bindExecutionObservation(e,t){if(t.admission.attemptId!==e.attemptId)throw new Error("native observation does not bind the original attempt");const n=operationKey(e),i=this.executionObservations.get(n);if(i&&!isDeepStrictEqual(i.source,t))throw new Error("native loaded observation changed");i||this.executionObservations.set(n,{source:structuredClone(t),loaded:!1})}nativeEventCapacity(e,t){const n=this.executionObservations.get(operationKey(e));return 200-(t?1:0)-(n&&!n.loaded?1:0)}async load(e){let t=null,n="0",i=null;const r=[];for(;;){const o=await this.client.load(await this.credential(e),{context:e.context,session_id:e.sessionId,history_generation:e.historyGeneration,branch_id:e.branchId,watermark:t,after:n,limit:200});this.assertPage(o,e,t,n),t=o.watermark;for(const e of o.events){if(e.sequence!==String(BigInt(n)+1n))throw new Error("central native event sequence has a gap");const t=decodeNativeChatEvent(e);if(isDeepStrictEqual(e.codec,codec))r.push(JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(t)));else if(!isDeepStrictEqual(e.codec,CENTRAL_RESPONSE_CONTROL_CODEC))throw new Error("central native event codec is not supported by this pinned Harness");n=e.sequence,i=e.event_id}if(o.next_after!==n||o.has_more&&BigInt(n)>=BigInt(t))throw new Error("central native page cursor does not match its fixed source");if(!o.has_more){if(n!==t)throw new Error("central native source ended before its fixed watermark");return this.heads.set(key(e),{watermark:t,lastEventId:i}),{codec:OPENCLAW_NATIVE_CODEC,events:r,watermark:t,writer:o.writer,terminal:o.terminal}}if(0===o.events.length)throw new Error("central native source made no page progress")}}prepareAppend(e){if(e.events.length>this.nativeEventCapacity(e.binding,Boolean(e.nativeOutcome)))throw new Error("native suffix must reserve its actual observation and terminal control rows");const t=this.heads.get(key(e.binding));if(!t||t.watermark!==e.expectedWatermark)throw new Error("native append has no exact loaded central source");let n=t.lastEventId;const i=e.events.map((t,i)=>{const r=Buffer.from(JSON.stringify(t),"utf8"),o=createHash("sha256").update(JSON.stringify([e.binding.sessionId,e.binding.historyGeneration,e.binding.branchId,String(BigInt(e.expectedWatermark)+BigInt(i)+1n)])).update(r).digest("hex"),a=encodeNativeChatEvent({eventId:`oc-${o}`,parentId:n,kind:t&&"object"==typeof t&&"type"in t&&"string"==typeof t.type?t.type:"native",codec:codec,content:r});return n=a.event_id,a});let r=null;const o=structuredClone(this.publicEvents.get(operationKey(e.binding))??[]),a=this.executionObservations.get(operationKey(e.binding)),s=(t,n,i)=>{const r=a.source,s="executed"===t?this.memoryReads.get(operationKey(e.binding)):void 0;o.push({type:executionObservationType,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,resolved_request_hash:r.resolvedRequestHash,payload:{phase:t,attempt:{...r.admission,...i?{nativeRunId:i.nativeRunId}:{}},read_watermark:r.readWatermark,source_ref:{id:n.event_id,digest:n.sha256},session_config_receipt:"loaded"===t?r.sessionConfigReceipt:null,runtime:null,partial_effective:{...r.loadedFacts,...i?.facts??{},...s?{memory_observation:s.status,memory_read_watermark:s.watermark}:{}}}})};if(a&&!a.loaded){const t=Buffer.from(JSON.stringify({type:"configuration.applied",...a.source}),"utf8"),r=`oc-loaded-${createHash("sha256").update(e.idempotencyKey).update(t).digest("hex")}`,o=encodeNativeChatEvent({eventId:r,parentId:n,kind:"configuration.applied",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:t});i.push(o),n=r,s("loaded",o)}if(e.publicProgress){if(e.nativeOutcome||0!==e.events.length||0===o.length)throw new Error("public native progress has invalid effect shape");const t=Buffer.from(JSON.stringify({type:"response.progress",response_id:e.binding.responseId,operation_id:e.binding.operationId,public_events_sha256:nativePayloadDigest(o)}),"utf8"),r=`oc-progress-${createHash("sha256").update(e.idempotencyKey).digest("hex")}`;i.push(encodeNativeChatEvent({eventId:r,parentId:n,kind:"response.progress",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:t})),n=r}if(e.nativeOutcome){const t=terminalProjection(e.binding,e.nativeOutcome),d=`oc-terminal-${createHash("sha256").update(e.idempotencyKey).digest("hex")}`,c={type:"response.terminal",operation_id:e.binding.operationId,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,native_outcome:e.nativeOutcome},l=encodeNativeChatEvent({eventId:d,parentId:n,kind:"response.terminal",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:Buffer.from(JSON.stringify(c),"utf8")});i.push(l),r={response_id:e.binding.responseId,status:t.status,event_id:d};const p=a?executedFacts(e.nativeOutcome):void 0;p&&s("executed",l,p),o.push(t.event)}const d={context:e.binding.context,session_id:e.binding.sessionId,history_generation:e.binding.historyGeneration,branch_id:e.binding.branchId,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,public_events:o,writer:e.binding.writer,expected_watermark:e.expectedWatermark,operation_id:e.binding.operationId,idempotency_key:e.idempotencyKey,events:i,terminal:r},c=chatAppendDigest(d),l={...d,payload_sha256:c};return{...structuredClone(e),codec:OPENCLAW_NATIVE_CODEC,payloadDigest:c,wire:l}}async append(e){const t=e.wire;if(chatAppendDigest(t)!==e.payloadDigest||t.payload_sha256!==e.payloadDigest)throw new Error("pending native append no longer matches its original digest");const n=await this.client.append(await this.credential(e.binding),t);return this.accept(e.binding,t,n),n}async receipt(e){const t=e.binding;try{const n=await this.client.receipt(await this.credential(t),{context:t.context,session_id:t.sessionId,history_generation:t.historyGeneration,branch_id:t.branchId,idempotency_key:e.idempotencyKey,payload_sha256:e.payloadDigest});if(n.operation_id!==t.operationId||!isDeepStrictEqual(n.writer,t.writer))throw new Error("original native receipt belongs to another operation/writer");return n}catch(e){if(e instanceof ChatStoreHttpError&&404===e.status&&"not_found"===e.code)return null;throw e}}assertPage(e,t,n,i){if(e.session_id!==t.sessionId||e.history_generation!==t.historyGeneration||e.branch_id!==t.branchId||!decimal(e.watermark)||null!==n&&e.watermark!==n||BigInt(e.watermark)<BigInt(i)||!Array.isArray(e.events)||"boolean"!=typeof e.has_more||!isDeepStrictEqual(e.writer,t.writer))throw new Error("central native load does not match the authorized fixed source/writer")}accept(e,t,n){if(!(n.operation_id===e.operationId&&n.previous_watermark===t.expected_watermark&&decimal(n.read_watermark)&&n.read_watermark===String(BigInt(t.expected_watermark)+BigInt(t.events.length))&&isDeepStrictEqual(n.event_ids,t.events.map(e=>e.event_id))&&isDeepStrictEqual(n.terminal,t.terminal)&&isDeepStrictEqual(n.writer,e.writer)))throw new Error("native append returned a receipt for different committed content");const i=this.heads.get(key(e));this.heads.set(key(e),{watermark:n.read_watermark,lastEventId:n.event_ids.at(-1)??i?.lastEventId??null});const r=operationKey(e),o=this.executionObservations.get(r);o&&t.public_events.some(e=>e.type===executionObservationType&&object(e.payload)&&"loaded"===e.payload.phase)&&(o.loaded=!0);const a=this.publicEvents.get(r);if(a){const e=t.public_events.filter(e=>e.type!==executionObservationType),i=e.slice(0,e.length-(t.terminal?1:0));if(!isDeepStrictEqual(a.slice(0,i.length),i))throw new Error("confirmed public events differ from their pending native buffer");n.terminal||a.length===i.length?this.publicEvents.delete(r):this.publicEvents.set(r,a.slice(i.length))}}}
1
+ import{createHash}from"node:crypto";import{isDeepStrictEqual}from"node:util";import{ChatStoreHttpError,chatAppendDigest,decodeNativeChatEvent,encodeNativeChatEvent}from"@beeos-ai/cloud-harness-sdk";import{OPENCLAW_NATIVE_CODEC,assertCentralNativeReceipt,nativePayloadDigest}from"./central-native-context-engine.js";import{generatedSessionName}from"./central-native-titles.js";import{nativeOutputFileIds,NativeArtifactDeliveryFailure}from"./central-native-output-files.js";const codec={name:"openclaw-session-events",version:"1"};export const CENTRAL_RESPONSE_CONTROL_CODEC={name:"beeos-response-control",version:"1"};const executionObservationType="response.beeos.execution_observation",decimal=e=>"string"==typeof e&&/^(0|[1-9][0-9]*)$/.test(e),key=e=>JSON.stringify([e.context.tenant_ref,e.context.scope_ref,e.sessionId,e.historyGeneration,e.branchId]),operationKey=e=>JSON.stringify([key(e),e.operationId,e.responseId,e.attemptId]),object=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),publicId=e=>"string"==typeof e&&/^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/.test(e)?e:null;export function publicModelRoute(e,t){if("string"==typeof e&&e.includes("/")){const t=e.indexOf("/");return[publicId(e.slice(0,t)),publicId(e.slice(t+1))]}return[publicId(t),publicId(e)]}function executedRoute(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.terminalReceipt)?t.terminalReceipt:{},i=object(n.effective)?n.effective:{},r=object(e.meta.executionTrace)?e.meta.executionTrace:{};return"string"==typeof i.responseModel?i.responseModel:"string"==typeof r.winnerModel?r.winnerModel:i.model}export function publicModelId(e){if("string"==typeof e&&0!==e.length)return publicId(e.includes("/")?`arouter_${e.replaceAll("/","_")}`:e)??void 0}function executedFacts(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.terminalReceipt)?t.terminalReceipt:{},i=object(n.effective)?n.effective:{},r=object(e.meta.executionTrace)?e.meta.executionTrace:{},o=object(e.meta.requestShaping)?e.meta.requestShaping:{},a="string"==typeof n.runId?n.runId:void 0,[s,d]=publicModelRoute(executedRoute(e),"string"==typeof i.provider?i.provider:r.winnerProvider);if(a&&s&&d)return{nativeRunId:a,facts:{actual_provider_id:s,actual_model_id:d,..."boolean"==typeof r.fallbackUsed?{fallback_used:r.fallbackUsed}:{},..."string"==typeof o.reasoning?{reasoning:o.reasoning}:{}}}}function terminalOutputItem(e){const t="string"==typeof e.toolCallId?e.toolCallId:"string"==typeof e.tool_call_id?e.tool_call_id:void 0,n="string"==typeof e.toolName?e.toolName:"string"==typeof e.tool_name?e.tool_name:void 0;if(t||n){if(!t||!n)throw new Error("native tool result lacks its tool call identity");return{type:"tool_summary",tool_call_id:t,tool_name:n,outcome:!0===e.isError?"failed":!1===e.isError?"succeeded":"unknown",summary:"string"==typeof e.text?e.text.slice(0,4096):""}}return"string"==typeof e.text&&e.text.length>0?{type:"output_text",text:e.text}:void 0}function terminalUsage(e){const t=object(e.meta.agentMeta)?e.meta.agentMeta:{},n=object(t.usage)?t.usage:void 0;if(!n)return;const i=e=>"number"==typeof e&&Number.isSafeInteger(e)&&e>=0?e:void 0,r=i(n.input),o=i(n.output);if(void 0===r&&void 0===o)return;const a=publicModelId(executedRoute(e));return{input_tokens:r??0,output_tokens:o??0,source:"provider",...a?{actual_model_id:a}:{}}}async function terminalProjection(e,t,n){const i=t.outcome;let r=["cancelled","aborted","superseded"].includes(i.reason)?"cancelled":["hard_timeout","timed_out","abandoned"].includes(i.reason)||["max_tokens","length","max_output_tokens"].includes(i.stopReason??"")?"incomplete":"completed"===i.reason&&"ok"===i.status?"completed":"failed";const o=[];let a;const s=new Set;try{for(const i of t.payloads){if(!object(i))throw new Error("native terminal payload is not a typed reply");const t=terminalOutputItem(i);t&&o.push(t);for(const t of nativeOutputFileIds(i))if(!s.has(t)){if(!n)throw new Error("authorized native output Files resolver is unavailable");o.push({type:"output_file",file:await n(e,t)}),s.add(t)}}}catch(e){if(!(e instanceof NativeArtifactDeliveryFailure))throw e;a=e,"completed"===r&&(r="failed")}const d=object(t.meta.agentMeta)?t.meta.agentMeta:{},c=terminalUsage(t);return{status:r,event:{type:"cancelled"===r?"response.failed":`response.${r}`,response:{id:e.responseId,status:r,output:o,..."string"==typeof d.model&&d.model.length>0?{model:d.model}:{},...c?{usage:c}:{},error:"failed"===r?{type:"harness_error",code:a?"artifact_delivery_failed":"harness_error",message:a?.message??(i.error||"The native harness could not complete this response.")}:null,incomplete_details:"incomplete"===r?{reason:"completed"===i.reason?"max_output_tokens":"runtime_interrupted"}:null}}}}export class StateCentralNativeStore{client;credential;titles;resolveOutputFile;writes=new Map;heads=new Map;publicEvents=new Map;memoryReads=new Map;executionObservations=new Map;constructor(e,t,n,i){this.client=e,this.credential=t,this.titles=n,this.resolveOutputFile=i}async recordGeneratedTitle(e,t){if(!this.titles)throw new Error("generated Session titles are unavailable");const n=generatedSessionName(t);if(!n)throw new Error("generated Session title is empty");return await this.titles.title(await this.credential(e),{context:e.context,session_id:e.sessionId,history_generation:e.historyGeneration,branch_id:e.branchId,name:n,idempotency_key:`title:${e.operationId}`})}withWrite(e,t){const n=key(e),i=(this.writes.get(n)??Promise.resolve()).then(t);return this.writes.set(n,i),i}async commitPublicProgress(e,t){await this.withWrite(e,async()=>{if(!this.publicEvents.get(operationKey(e))?.length)return;if(0!==(await t.list(e.sessionId)).length)throw new Error("native progress has unresolved original writes");const n=await this.load(e);if(n.terminal?.response_id===e.responseId)throw new Error("original native Response is already terminal");const i=structuredClone(this.publicEvents.get(operationKey(e))??[]),r=nativePayloadDigest(i),o=await this.prepareAppend({binding:e,events:[],expectedWatermark:n.watermark,publicProgress:!0,idempotencyKey:`progress:${e.operationId}:${n.watermark}:${r}`,nativeSnapshotDigest:r});await t.put(o);const a=await this.append(o);assertCentralNativeReceipt(o,a),await t.complete(o,a)})}recordPublicEvent(e,t){const n=operationKey(e),i=this.publicEvents.get(n)??[];i.push(structuredClone(t)),this.publicEvents.set(n,i)}recordMemoryRead(e,t){if("read"===t.status&&!t.watermark)throw new Error("actual Memory recall omitted its read watermark");this.memoryReads.set(operationKey(e),structuredClone(t))}bindExecutionObservation(e,t){if(t.admission.attemptId!==e.attemptId)throw new Error("native observation does not bind the original attempt");const n=operationKey(e),i=this.executionObservations.get(n);if(i&&!isDeepStrictEqual(i.source,t))throw new Error("native loaded observation changed");i||this.executionObservations.set(n,{source:structuredClone(t),loaded:!1})}nativeEventCapacity(e,t){const n=this.executionObservations.get(operationKey(e));return 200-(t?1:0)-(n&&!n.loaded?1:0)}async load(e){let t=null,n="0",i=null;const r=[];for(;;){const o=await this.client.load(await this.credential(e),{context:e.context,session_id:e.sessionId,history_generation:e.historyGeneration,branch_id:e.branchId,watermark:t,after:n,limit:200});this.assertPage(o,e,t,n),t=o.watermark;for(const e of o.events){if(e.sequence!==String(BigInt(n)+1n))throw new Error("central native event sequence has a gap");const t=decodeNativeChatEvent(e);if(isDeepStrictEqual(e.codec,codec))r.push(JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(t)));else if(!isDeepStrictEqual(e.codec,CENTRAL_RESPONSE_CONTROL_CODEC))throw new Error("central native event codec is not supported by this pinned Harness");n=e.sequence,i=e.event_id}if(o.next_after!==n||o.has_more&&BigInt(n)>=BigInt(t))throw new Error("central native page cursor does not match its fixed source");if(!o.has_more){if(n!==t)throw new Error("central native source ended before its fixed watermark");return this.heads.set(key(e),{watermark:t,lastEventId:i}),{codec:OPENCLAW_NATIVE_CODEC,events:r,watermark:t,writer:o.writer,terminal:o.terminal}}if(0===o.events.length)throw new Error("central native source made no page progress")}}async prepareAppend(e){if((e=structuredClone(e)).events.length>this.nativeEventCapacity(e.binding,Boolean(e.nativeOutcome)))throw new Error("native suffix must reserve its actual observation and terminal control rows");const t=this.heads.get(key(e.binding));if(!t||t.watermark!==e.expectedWatermark)throw new Error("native append has no exact loaded central source");let n=t.lastEventId;const i=e.events.map((t,i)=>{const r=Buffer.from(JSON.stringify(t),"utf8"),o=createHash("sha256").update(JSON.stringify([e.binding.sessionId,e.binding.historyGeneration,e.binding.branchId,String(BigInt(e.expectedWatermark)+BigInt(i)+1n)])).update(r).digest("hex"),a=encodeNativeChatEvent({eventId:`oc-${o}`,parentId:n,kind:t&&"object"==typeof t&&"type"in t&&"string"==typeof t.type?t.type:"native",codec:codec,content:r});return n=a.event_id,a});let r=null;const o=structuredClone(this.publicEvents.get(operationKey(e.binding))??[]),a=this.executionObservations.get(operationKey(e.binding)),s=(t,n,i)=>{const r=a.source,s="executed"===t?this.memoryReads.get(operationKey(e.binding)):void 0;o.push({type:executionObservationType,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,resolved_request_hash:r.resolvedRequestHash,payload:{phase:t,attempt:{...r.admission,...i?{nativeRunId:i.nativeRunId}:{}},read_watermark:r.readWatermark,source_ref:{id:n.event_id,digest:n.sha256},session_config_receipt:"loaded"===t?r.sessionConfigReceipt:null,runtime:null,partial_effective:{...r.loadedFacts,...i?.facts??{},...s?{memory_observation:s.status,memory_read_watermark:s.watermark}:{}}}})};if(a&&!a.loaded){const t=Buffer.from(JSON.stringify({type:"configuration.applied",...a.source}),"utf8"),r=`oc-loaded-${createHash("sha256").update(e.idempotencyKey).update(t).digest("hex")}`,o=encodeNativeChatEvent({eventId:r,parentId:n,kind:"configuration.applied",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:t});i.push(o),n=r,s("loaded",o)}if(e.publicProgress){if(e.nativeOutcome||0!==e.events.length||0===o.length)throw new Error("public native progress has invalid effect shape");const t=Buffer.from(JSON.stringify({type:"response.progress",response_id:e.binding.responseId,operation_id:e.binding.operationId,public_events_sha256:nativePayloadDigest(o)}),"utf8"),r=`oc-progress-${createHash("sha256").update(e.idempotencyKey).digest("hex")}`;i.push(encodeNativeChatEvent({eventId:r,parentId:n,kind:"response.progress",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:t})),n=r}if(e.nativeOutcome){const t=await terminalProjection(e.binding,e.nativeOutcome,this.resolveOutputFile),d=`oc-terminal-${createHash("sha256").update(e.idempotencyKey).digest("hex")}`,c={type:"response.terminal",operation_id:e.binding.operationId,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,native_outcome:e.nativeOutcome},l=encodeNativeChatEvent({eventId:d,parentId:n,kind:"response.terminal",codec:CENTRAL_RESPONSE_CONTROL_CODEC,content:Buffer.from(JSON.stringify(c),"utf8")});i.push(l),r={response_id:e.binding.responseId,status:t.status,event_id:d};const p=a?executedFacts(e.nativeOutcome):void 0;p&&s("executed",l,p),o.push(t.event)}const d={context:e.binding.context,session_id:e.binding.sessionId,history_generation:e.binding.historyGeneration,branch_id:e.binding.branchId,response_id:e.binding.responseId,attempt_id:e.binding.attemptId,public_events:o,writer:e.binding.writer,expected_watermark:e.expectedWatermark,operation_id:e.binding.operationId,idempotency_key:e.idempotencyKey,events:i,terminal:r},c=chatAppendDigest(d),l={...d,payload_sha256:c};return{...structuredClone(e),codec:OPENCLAW_NATIVE_CODEC,payloadDigest:c,wire:l}}async append(e){const t=e.wire;if(chatAppendDigest(t)!==e.payloadDigest||t.payload_sha256!==e.payloadDigest)throw new Error("pending native append no longer matches its original digest");const n=await this.client.append(await this.credential(e.binding),t);return this.accept(e.binding,t,n),n}async receipt(e){const t=e.binding;try{const n=await this.client.receipt(await this.credential(t),{context:t.context,session_id:t.sessionId,history_generation:t.historyGeneration,branch_id:t.branchId,idempotency_key:e.idempotencyKey,payload_sha256:e.payloadDigest});if(n.operation_id!==t.operationId||!isDeepStrictEqual(n.writer,t.writer))throw new Error("original native receipt belongs to another operation/writer");return n}catch(e){if(e instanceof ChatStoreHttpError&&404===e.status&&"not_found"===e.code)return null;throw e}}assertPage(e,t,n,i){if(e.session_id!==t.sessionId||e.history_generation!==t.historyGeneration||e.branch_id!==t.branchId||!decimal(e.watermark)||null!==n&&e.watermark!==n||BigInt(e.watermark)<BigInt(i)||!Array.isArray(e.events)||"boolean"!=typeof e.has_more||!isDeepStrictEqual(e.writer,t.writer))throw new Error("central native load does not match the authorized fixed source/writer")}accept(e,t,n){if(!(n.operation_id===e.operationId&&n.previous_watermark===t.expected_watermark&&decimal(n.read_watermark)&&n.read_watermark===String(BigInt(t.expected_watermark)+BigInt(t.events.length))&&isDeepStrictEqual(n.event_ids,t.events.map(e=>e.event_id))&&isDeepStrictEqual(n.terminal,t.terminal)&&isDeepStrictEqual(n.writer,e.writer)))throw new Error("native append returned a receipt for different committed content");const i=this.heads.get(key(e));this.heads.set(key(e),{watermark:n.read_watermark,lastEventId:n.event_ids.at(-1)??i?.lastEventId??null});const r=operationKey(e),o=this.executionObservations.get(r);o&&t.public_events.some(e=>e.type===executionObservationType&&object(e.payload)&&"loaded"===e.payload.phase)&&(o.loaded=!0);const a=this.publicEvents.get(r);if(a){const e=t.public_events.filter(e=>e.type!==executionObservationType),i=e.slice(0,e.length-(t.terminal?1:0));if(!isDeepStrictEqual(a.slice(0,i.length),i))throw new Error("confirmed public events differ from their pending native buffer");n.terminal||a.length===i.length?this.publicEvents.delete(r):this.publicEvents.set(r,a.slice(i.length))}}}
@@ -1 +1 @@
1
- import{isDeepStrictEqual}from"node:util";import{CLOUD_RUNTIME_EXECUTION_GRANT_DOMAIN,RUNTIME_HASH_DOMAINS}from"@beeos-ai/beeos-types/runtime";import{assertCentralNativeReceipt}from"./central-native-context-engine.js";import{runtimeMessageHash}from"./runtime-message-channel-contract.js";const object=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),promptText=e=>{if("string"==typeof e.text&&e.text.length>0)return e.text;return(Array.isArray(e.parts)?e.parts:[]).filter(object).filter(e=>"text"===e.type&&"string"==typeof e.text).map(e=>e.text).join("\n")},text=e=>"string"==typeof e&&e.length>0,decimal=e=>"string"==typeof e&&/^(0|[1-9][0-9]*)$/.test(e),associationKeys=["context","session_id","history_generation","branch_id","writer","response_id","attempt_id","watermark","config_pin","persona_ref"],GRANT_CLOCK_SKEW_SECONDS=30,grantInvalid=e=>new Error(`central native original signed intent is invalid: ${e}`),grantDecodeReason=e=>{const t=e.split(".")[1];if(!t)return"grant_signature_invalid";let r;try{const e=JSON.parse(Buffer.from(t,"base64url").toString("utf8"));if(!object(e))return"grant_signature_invalid";r=e}catch{return"grant_signature_invalid"}return r.iss!==CLOUD_RUNTIME_EXECUTION_GRANT_DOMAIN.issuer?"grant_issuer_mismatch":r.aud!==CLOUD_RUNTIME_EXECUTION_GRANT_DOMAIN.audience?"grant_audience_mismatch":r.purpose!==CLOUD_RUNTIME_EXECUTION_GRANT_DOMAIN.purpose?"grant_binding_mismatch":"grant_signature_invalid"};export function isCentralNativeResponse(e){const t=e.message?.payload,r=t?.request;return 2===t?.schemaVersion&&"session/prompt"===t.method&&object(r)&&object(r.params)&&Object.hasOwn(r.params,"centralChat")}export function verifyCentralNativeIntent(e){const t=e.executionGrant,r=e.request;if(!t)throw grantInvalid("grant_binding_mismatch");const i=e.verifier.verifyAndDecodeGrant(t);if(!i)throw grantInvalid(grantDecodeReason(t));const n=i.claims,a=object(r.request)?r.request:{},s=object(a.params)?a.params:{},o=object(s.centralChat)?s.centralChat:{},c=object(r.command)?r.command:{},d=object(c.context)?c.context:{},p=object(d.conversation)?d.conversation:{},l=object(o.context)?o.context:{},m=object(o.writer)?o.writer:{},u=object(o.config_pin)?o.config_pin:{},h=u.credential_set_ref,g=()=>{const t=e.getLease();if(!t||t.instanceId!==e.lease.instanceId||t.leaseId!==e.lease.leaseId||t.handlerIdentity!==e.lease.handlerIdentity||t.runtimeEpoch!==e.lease.runtimeEpoch||!Number.isFinite(Date.parse(t.leaseExpiresAt))||Date.parse(t.leaseExpiresAt)<=Date.now())throw new Error("central native execution is fenced")},_=Math.floor(Date.now()/1e3);if(!Number.isSafeInteger(n.iat)||!Number.isSafeInteger(n.exp)||n.exp<=n.iat||n.exp-n.iat>60)throw grantInvalid("grant_binding_mismatch");if(n.exp+30<_)throw grantInvalid("grant_expired");if(n.iat>_+30)throw grantInvalid("grant_iat_future");if(!object(r)||2!==r.schemaVersion||"session/prompt"!==r.method||!Object.hasOwn(s,"centralChat")||"string"!=typeof r.executionGrantHash||!/^[a-f0-9]{64}$/.test(r.executionGrantHash)||"cloud"!==r.authorityRealm||!object(r.cloudSubject)||r.cloudSubject.instanceId!==e.lease.instanceId||!isDeepStrictEqual(r.cloudSubject,n.cloudSubject)||r.instanceId!==e.lease.instanceId||r.leaseId!==e.lease.leaseId||r.runtimeHandlerIdentity!==e.lease.handlerIdentity||r.dispatchEpoch!==e.lease.runtimeEpoch||"cloud"!==n.authorityRealm||"session/prompt"!==n.method||"conversation"!==n.scope||"start"!==n.executionMode||n.platformConversationId!==o.session_id||n.historyGeneration!==o.history_generation||n.platformAgentId!==s.platformAgentId||!text(n.runtimeAgentUid)||s.conversationId!==o.session_id||"conversation"!==d.scope||p.runtimeConversationUid!==o.session_id||p.runtimeSessionKey!==o.session_id||d.historyGeneration!==o.history_generation||d.operationId!==r.operationId||d.runtimeInstanceUid!==r.instanceId||d.dispatchEpoch!==r.dispatchEpoch||d.paramsHash!==r.paramsHash||!isDeepStrictEqual(n.command,c)||n.sub!==e.lease.handlerIdentity||n.handlerIdentity!==e.lease.handlerIdentity||["operationId","requestMessageId","instanceId","leaseId","dispatchEpoch","requestHash","paramsHash","commandHash","idempotencyKeyHash"].some(e=>!text(r[e])||n[e]!==r[e])||"2.0"!==a.jsonrpc||"session/prompt"!==a.method||"session.prompt"!==c.name||!text(s.runtimeRunId)||s.taskId!==r.operationId||s.taskRequestMessageId!==r.requestMessageId||runtimeMessageHash(RUNTIME_HASH_DOMAINS.request,a)!==r.requestHash||runtimeMessageHash(RUNTIME_HASH_DOMAINS.params,{method:r.method,params:s})!==r.paramsHash||runtimeMessageHash(RUNTIME_HASH_DOMAINS.command,{command:c})!==r.commandHash||![o.session_id,o.history_generation,o.branch_id,o.response_id,o.attempt_id,l.tenant_ref,l.scope_ref,l.request_id,m.writer_id,m.writer_epoch].every(text)||!Number.isSafeInteger(l.authorization_revision)||l.authorization_revision<1||!Number.isSafeInteger(l.erasure_epoch)||l.erasure_epoch<0||!decimal(o.history_generation)||!decimal(o.watermark)||!decimal(m.writer_epoch)||"0"===m.writer_epoch||Object.keys(o).length!==associationKeys.length||!associationKeys.every(e=>Object.hasOwn(o,e))||4!==Object.keys(u).length||u.agent_id!==s.platformAgentId||!text(u.revision)||"string"!=typeof u.content_sha256||!/^[a-f0-9]{64}$/.test(u.content_sha256)||null!==h&&(!object(h)||2!==Object.keys(h).length||!text(h.set_id)||!Number.isSafeInteger(h.version)||h.version<1)||null!==o.persona_ref&&(!object(o.persona_ref)||2!==Object.keys(o.persona_ref).length||!text(o.persona_ref.persona_id)||!text(o.persona_ref.revision)))throw grantInvalid("grant_binding_mismatch");g();return{binding:{sessionId:o.session_id,historyGeneration:o.history_generation,branchId:o.branch_id,responseId:o.response_id,attemptId:o.attempt_id,operationId:r.operationId,context:l,writer:m},params:structuredClone(s),assertCurrent:g}}export class CentralNativeResponse{options;constructor(e){this.options=e}async execute(e){const t=this.options;await t.verifier.refresh();const r=e.delivery.message.payload;if("runtime_rpc_request"!==e.delivery.message.type||"completed"!==e.delivery.message.state||e.delivery.message.message_id!==r.requestMessageId||e.delivery.message.channel_id!==r.operationId)throw new Error("central native original delivery is invalid");const i=e.delivery.executionGrant,{binding:n,params:a,assertCurrent:s}=verifyCentralNativeIntent({request:r,executionGrant:i,verifier:t.verifier,lease:e.lease,getLease:t.getLease});e.onVerified?.({operationId:r.operationId,requestMessageId:r.requestMessageId,requestHash:r.requestHash,dispatchEpoch:r.dispatchEpoch,method:"session/prompt"}),t.bindCredential(n,i,r.requestHash,{requestMessageId:r.requestMessageId,verifier:t.verifier});const o=await t.pending.terminal(n);if(o){const e=o.request??{binding:o.binding,idempotencyKey:o.receipt.idempotency_key,payloadDigest:o.receipt.payload_sha256},{context:r,...i}=e.binding,{context:a,...c}=n;if(!isDeepStrictEqual(i,c)||r.tenant_ref!==a.tenant_ref||r.scope_ref!==a.scope_ref)throw new Error("central terminal original binding changed");const d=await t.store.receipt({...e,binding:n});if(s(),!d?.terminal||o.receipt&&!isDeepStrictEqual(d,o.receipt))throw new Error("central terminal outcome is unknown");return o.request&&(assertCentralNativeReceipt(o.request,d),await t.pending.complete(o.request,d)),await this.settleJournal(n.operationId),d}const c=await t.store.load(n);if(c.terminal?.response_id===n.responseId)throw new Error("original Response is already terminal; reconcile its original receipt before native execution");const d="completed"!==c.terminal?.status;if(s(),e.signal.aborted)throw new Error("central native execution stopped before dispatch; original owner stop reconciliation is required");let p=await t.journal.get(n.operationId);if(p&&("session.prompt"!==p.command||p.paramsHash!==r.paramsHash||p.runtimeEpoch!==e.lease.runtimeEpoch||"prepared"!==p.phase))throw new Error("central native execution already started; original terminal reconciliation is required");if(p=await t.journal.acceptMessageRequest({operationId:n.operationId,command:"session.prompt",paramsHash:r.paramsHash,runtimeEpoch:e.lease.runtimeEpoch,requestMessageId:r.requestMessageId,requestHash:r.requestHash}),s(),await t.journal.transition({operationId:n.operationId,expectedRevision:p.revision,phase:"started"}),e.signal.aborted)throw new Error("central native execution stopped before dispatch; original owner stop reconciliation is required");const l=await t.host.run({params:structuredClone(a),binding:n,requestMessageId:r.requestMessageId,signal:e.signal,assertCurrent:s});s();const m=await t.pending.terminal(n);if(!m?.receipt||!m.receipt.terminal||m.receipt.terminal.status!==l.status)throw new Error("native owner did not confirm its original atomic suffix/terminal transaction");const u=await t.store.receipt({binding:n,idempotencyKey:m.receipt.idempotency_key,payloadDigest:m.receipt.payload_sha256});if(s(),!u||!isDeepStrictEqual(u,m.receipt))throw new Error("original native terminal receipt is unavailable");return await this.settleJournal(n.operationId),"completed"===l.status&&d&&t.recordGeneratedTitle?.({binding:n,question:promptText(a),answer:l.finalText??""}),u}async settleJournal(e){let t=await this.options.journal.get(e);"started"===t?.phase&&(t=await this.options.journal.transition({operationId:e,expectedRevision:t.revision,phase:"effect_committed"})),"effect_committed"===t?.phase&&await this.options.journal.transition({operationId:e,expectedRevision:t.revision,phase:"projection_committed"})}}
1
+ import{createHash}from"node:crypto";import{isDeepStrictEqual}from"node:util";import{CLOUD_RUNTIME_EXECUTION_GRANT_DOMAIN,RUNTIME_HASH_DOMAINS}from"@beeos-ai/beeos-types/runtime";import{assertCentralNativeReceipt}from"./central-native-context-engine.js";import{runtimeMessageHash}from"./runtime-message-channel-contract.js";const object=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),promptText=e=>{if("string"==typeof e.text&&e.text.length>0)return e.text;return(Array.isArray(e.parts)?e.parts:[]).filter(object).filter(e=>"text"===e.type&&"string"==typeof e.text).map(e=>e.text).join("\n")},text=e=>"string"==typeof e&&e.length>0,decimal=e=>"string"==typeof e&&/^(0|[1-9][0-9]*)$/.test(e),associationKeys=["context","session_id","history_generation","branch_id","writer","response_id","attempt_id","watermark","config_pin","persona_ref"],GRANT_CLOCK_SKEW_SECONDS=30,grantInvalid=e=>new Error(`central native original signed intent is invalid: ${e}`),grantDecodeReason=e=>{const t=e.split(".")[1];if(!t)return"grant_signature_invalid";let r;try{const e=JSON.parse(Buffer.from(t,"base64url").toString("utf8"));if(!object(e))return"grant_signature_invalid";r=e}catch{return"grant_signature_invalid"}return r.iss!==CLOUD_RUNTIME_EXECUTION_GRANT_DOMAIN.issuer?"grant_issuer_mismatch":r.aud!==CLOUD_RUNTIME_EXECUTION_GRANT_DOMAIN.audience?"grant_audience_mismatch":r.purpose!==CLOUD_RUNTIME_EXECUTION_GRANT_DOMAIN.purpose?"grant_binding_mismatch":"grant_signature_invalid"};export function isCentralNativeResponse(e){const t=e.message?.payload,r=t?.request;return 2===t?.schemaVersion&&"session/prompt"===t.method&&object(r)&&object(r.params)&&Object.hasOwn(r.params,"centralChat")}const verifiedIntents=new WeakMap;export function retainedCentralNativeRequest(e){const t=verifiedIntents.get(e);return t&&isDeepStrictEqual(e.request,t)?structuredClone(t):null}export function verifyCentralNativeIntent(e){const t=e.executionGrant,r=e.request;if(!t)throw grantInvalid("grant_binding_mismatch");const a=e.verifier.verifyAndDecodeGrant(t);if(!a)throw grantInvalid(grantDecodeReason(t));const n=a.claims,i=object(r.request)?r.request:{},s=object(i.params)?i.params:{},o=object(s.centralChat)?s.centralChat:{},c=object(r.command)?r.command:{},d=object(c.context)?c.context:{},p=object(d.conversation)?d.conversation:{},l=object(o.context)?o.context:{},u=object(o.writer)?o.writer:{},h=object(o.config_pin)?o.config_pin:{},m=h.credential_set_ref,g=()=>{const t=e.getLease();if(!t||t.instanceId!==e.lease.instanceId||t.leaseId!==e.lease.leaseId||t.handlerIdentity!==e.lease.handlerIdentity||t.runtimeEpoch!==e.lease.runtimeEpoch||!Number.isFinite(Date.parse(t.leaseExpiresAt))||Date.parse(t.leaseExpiresAt)<=Date.now())throw new Error("central native execution is fenced")},_=Math.floor(Date.now()/1e3);if(!Number.isSafeInteger(n.iat)||!Number.isSafeInteger(n.exp)||n.exp<=n.iat||n.exp-n.iat>60)throw grantInvalid("grant_binding_mismatch");if(n.exp+30<_)throw grantInvalid("grant_expired");if(n.iat>_+30)throw grantInvalid("grant_iat_future");if(!object(r)||2!==r.schemaVersion||"session/prompt"!==r.method||!Object.hasOwn(s,"centralChat")||"string"!=typeof r.executionGrantHash||!/^[a-f0-9]{64}$/.test(r.executionGrantHash)||"cloud"!==r.authorityRealm||!object(r.cloudSubject)||r.cloudSubject.instanceId!==e.lease.instanceId||!isDeepStrictEqual(r.cloudSubject,n.cloudSubject)||r.instanceId!==e.lease.instanceId||r.leaseId!==e.lease.leaseId||r.runtimeHandlerIdentity!==e.lease.handlerIdentity||r.dispatchEpoch!==e.lease.runtimeEpoch||"cloud"!==n.authorityRealm||"session/prompt"!==n.method||"conversation"!==n.scope||"start"!==n.executionMode||n.platformConversationId!==o.session_id||n.historyGeneration!==o.history_generation||n.platformAgentId!==s.platformAgentId||!text(n.runtimeAgentUid)||s.conversationId!==o.session_id||"conversation"!==d.scope||p.runtimeConversationUid!==o.session_id||p.runtimeSessionKey!==o.session_id||d.historyGeneration!==o.history_generation||d.operationId!==r.operationId||d.runtimeInstanceUid!==r.instanceId||d.dispatchEpoch!==r.dispatchEpoch||d.paramsHash!==r.paramsHash||!isDeepStrictEqual(n.command,c)||n.sub!==e.lease.handlerIdentity||n.handlerIdentity!==e.lease.handlerIdentity||["operationId","requestMessageId","instanceId","leaseId","dispatchEpoch","requestHash","paramsHash","commandHash","idempotencyKeyHash"].some(e=>!text(r[e])||n[e]!==r[e])||"2.0"!==i.jsonrpc||"session/prompt"!==i.method||"session.prompt"!==c.name||!text(s.runtimeRunId)||s.taskId!==r.operationId||s.taskRequestMessageId!==r.requestMessageId||runtimeMessageHash(RUNTIME_HASH_DOMAINS.request,i)!==r.requestHash||runtimeMessageHash(RUNTIME_HASH_DOMAINS.params,{method:r.method,params:s})!==r.paramsHash||runtimeMessageHash(RUNTIME_HASH_DOMAINS.command,{command:c})!==r.commandHash||![o.session_id,o.history_generation,o.branch_id,o.response_id,o.attempt_id,l.tenant_ref,l.scope_ref,l.request_id,u.writer_id,u.writer_epoch].every(text)||!Number.isSafeInteger(l.authorization_revision)||l.authorization_revision<1||!Number.isSafeInteger(l.erasure_epoch)||l.erasure_epoch<0||!decimal(o.history_generation)||!decimal(o.watermark)||!decimal(u.writer_epoch)||"0"===u.writer_epoch||Object.keys(o).length!==associationKeys.length||!associationKeys.every(e=>Object.hasOwn(o,e))||4!==Object.keys(h).length||h.agent_id!==s.platformAgentId||!text(h.revision)||"string"!=typeof h.content_sha256||!/^[a-f0-9]{64}$/.test(h.content_sha256)||null!==m&&(!object(m)||2!==Object.keys(m).length||!text(m.set_id)||!Number.isSafeInteger(m.version)||m.version<1)||null!==o.persona_ref&&(!object(o.persona_ref)||2!==Object.keys(o.persona_ref).length||!text(o.persona_ref.persona_id)||!text(o.persona_ref.revision)))throw grantInvalid("grant_binding_mismatch");g();const I={sessionId:o.session_id,historyGeneration:o.history_generation,branchId:o.branch_id,responseId:o.response_id,attemptId:o.attempt_id,operationId:r.operationId,context:l,writer:u},f={request:structuredClone(r),binding:I,params:structuredClone(s),assertCurrent:g};return verifiedIntents.set(f,structuredClone(r)),f}export class CentralNativeResponse{options;constructor(e){this.options=e}async execute(e){const t=this.options;await t.verifier.refresh();const r=e.delivery.message.payload;if("runtime_rpc_request"!==e.delivery.message.type||"completed"!==e.delivery.message.state||e.delivery.message.message_id!==r.requestMessageId||e.delivery.message.channel_id!==r.operationId)throw new Error("central native original delivery is invalid");const a=e.delivery.executionGrant,n=verifyCentralNativeIntent({request:r,executionGrant:a,verifier:t.verifier,lease:e.lease,getLease:t.getLease}),{binding:i,params:s,assertCurrent:o}=n;e.onVerified?.({operationId:r.operationId,requestMessageId:r.requestMessageId,requestHash:r.requestHash,dispatchEpoch:r.dispatchEpoch,method:"session/prompt"}),t.bindCredential(i,a,r.requestHash,{requestMessageId:r.requestMessageId,verifier:t.verifier});const c=await t.pending.terminal(i);if(c){const e=c.request??{binding:c.binding,idempotencyKey:c.receipt.idempotency_key,payloadDigest:c.receipt.payload_sha256},{context:r,...a}=e.binding,{context:n,...s}=i;if(!isDeepStrictEqual(a,s)||r.tenant_ref!==n.tenant_ref||r.scope_ref!==n.scope_ref)throw new Error("central terminal original binding changed");const d=await t.store.receipt({...e,binding:i});if(o(),!d?.terminal||c.receipt&&!isDeepStrictEqual(d,c.receipt))throw new Error("central terminal outcome is unknown");return c.request&&(assertCentralNativeReceipt(c.request,d),await t.pending.complete(c.request,d)),await this.settleJournal(i.operationId),d}const d=await t.store.load(i);if(d.terminal?.response_id===i.responseId)throw new Error("original Response is already terminal; reconcile its original receipt before native execution");const p="completed"!==d.terminal?.status;if(o(),e.signal.aborted)throw new Error("central native execution stopped before dispatch; original owner stop reconciliation is required");let l=await t.journal.get(i.operationId);if(l&&("session.prompt"!==l.command||l.paramsHash!==r.paramsHash||l.runtimeEpoch!==e.lease.runtimeEpoch||"prepared"!==l.phase))throw new Error("central native execution already started; original terminal reconciliation is required");l=await t.journal.acceptMessageRequest({operationId:i.operationId,command:"session.prompt",paramsHash:r.paramsHash,runtimeEpoch:e.lease.runtimeEpoch,requestMessageId:r.requestMessageId,requestHash:r.requestHash}),o();const u={operationId:i.operationId,lease:t.getLease(),currentCentralIntent:n},h=await t.channel.history(u);if(o(),"found"!==h.status||h.snapshot.terminal||h.snapshot.cancelRequested)throw new Error("central native start history is unavailable or closed");let m=h.snapshot.started;if(!m){if(e.signal.aborted)throw new Error("central native execution stopped before dispatch; original owner stop reconciliation is required");m=(await t.channel.append({...u,lease:t.getLease(),executionGrant:a,type:"runtime_operation_started",payload:{schemaVersion:1,operationId:i.operationId,requestMessageId:r.requestMessageId,requestHash:r.requestHash,dispatchEpoch:e.lease.runtimeEpoch,method:"session/prompt",executionGrantHash:createHash("sha256").update(a).digest("hex"),handlerIdentity:e.lease.handlerIdentity,executionMode:"start",claimedAt:l.updatedAt}})).message}const g=m.payload;if("runtime_operation_started"!==m.type||m.publisher_id!==e.lease.handlerIdentity||g.handlerIdentity!==e.lease.handlerIdentity||"start"!==g.executionMode||g.claimedAt!==l.updatedAt||"string"!=typeof g.executionGrantHash||!/^[a-f0-9]{64}$/.test(g.executionGrantHash))throw new Error("central native Started does not match the prepared local execution");if(o(),await t.journal.transition({operationId:i.operationId,expectedRevision:l.revision,phase:"started"}),e.signal.aborted)throw new Error("central native execution stopped before dispatch; original owner stop reconciliation is required");const _=await t.host.run({params:structuredClone(s),binding:i,requestMessageId:r.requestMessageId,signal:e.signal,assertCurrent:o});o();const I=await t.pending.terminal(i);if(!I?.receipt||!I.receipt.terminal||I.receipt.terminal.status!==_.status)throw new Error("native owner did not confirm its original atomic suffix/terminal transaction");const f=await t.store.receipt({binding:i,idempotencyKey:I.receipt.idempotency_key,payloadDigest:I.receipt.payload_sha256});if(o(),!f||!isDeepStrictEqual(f,I.receipt))throw new Error("original native terminal receipt is unavailable");return await this.settleJournal(i.operationId),"completed"===_.status&&p&&t.recordGeneratedTitle?.({binding:i,question:promptText(s),answer:_.finalText??""}),f}async settleJournal(e){let t=await this.options.journal.get(e);"started"===t?.phase&&(t=await this.options.journal.transition({operationId:e,expectedRevision:t.revision,phase:"effect_committed"})),"effect_committed"===t?.phase&&await this.options.journal.transition({operationId:e,expectedRevision:t.revision,phase:"projection_committed"})}}
@@ -1 +1 @@
1
- import{RUNTIME_HASH_DOMAINS}from"@beeos-ai/beeos-types/runtime";import{HarnessProtocolError,RuntimeMessagePlane}from"@beeos-ai/cloud-harness-sdk";import{isDeepStrictEqual}from"node:util";import{runtimeLeaseHttp}from"./message-service-runtime-authenticated-fetch.js";import{retainedVerifiedNativePrompt}from"./native-prompt-authority.js";import{runtimeMessageHash,semanticEqual,validateRuntimeCancelEnvelope,validateRuntimeRequestEnvelope}from"./runtime-message-channel-contract.js";export class RuntimeMessageChannelProtocolError extends Error{status;code;constructor(e,t,r){super(e),this.status=t,this.code=r,this.name="RuntimeMessageChannelProtocolError"}}export class MessageServiceRuntimeMessageChannel{options;plane;constructor(e){if(this.options=e,!e.scopedDeliveryKey)throw new Error("Message runtime delivery credential is required");this.plane=new RuntimeMessagePlane(runtimeLeaseHttp(e.serviceUrl,(t,r)=>e.transport.fetchBounded(t,r)))}async read(e){const t=await this.invoke(()=>this.plane.readDeliveries(this.credential(e.lease),{maxCount:e.maxCount,blockMs:e.blockMs},e.signal),"runtime delivery read failed");if(!record(t)||"deliveries"!==t.status||!Array.isArray(t.deliveries)||t.deliveries.length>e.maxCount||!t.deliveries.every(isDelivery)||new Set(t.deliveries.map(e=>e.deliveryId)).size!==t.deliveries.length)throw new RuntimeMessageChannelProtocolError("Message Service returned invalid runtime deliveries");return t.deliveries}async renew(e){const t=await this.invoke(()=>this.plane.renewDeliveries(this.credential(e.lease),e.deliveryIds),"runtime delivery renew failed");if(!(record(t)&&"renewed"===t.status&&strings(t.renewed)&&strings(t.notPending)&&exactIdPartition(e.deliveryIds,t.renewed,t.notPending)))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid delivery renewal");return{renewed:t.renewed,notPending:t.notPending}}async acknowledge(e){const t=await this.invoke(()=>this.plane.ackDeliveries(this.credential(e.lease),e.deliveryIds),"runtime delivery ack failed");if(!record(t)||"acknowledged"!==t.status||!strings(t.deliveryIds)||!sameIds(t.deliveryIds,e.deliveryIds))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid delivery acknowledgement")}async history(e){let t;try{t=await this.plane.operationHistory(this.credential(e.lease),e.operationId)}catch(e){if(!(e instanceof HarnessProtocolError))throw e;if(404===e.status)return{status:"not_found"};if(410===e.status)return{status:"expired"};throw harnessFailure(e,"runtime history read failed")}if(!isHistory(t,e.operationId))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid operation history");return{status:"found",snapshot:t}}async append(e){const t=appendResult(await this.invoke(()=>this.plane.appendOperationMessage(this.credential(e.lease,e.executionGrant),e.operationId,{type:e.type,payload:e.payload}),"runtime message-channel append failed")),r="runtime_rpc_response"===e.type?e.payload.requestMessageId:void 0;if(t.message.channel_id!==e.operationId||t.message.type!==e.type||t.message.in_reply_to!==r||!semanticEqual(t.message.payload,e.payload))throw new RuntimeMessageChannelProtocolError("Message Service append response correlation mismatch");return t}credential(e,t){return{runtimeLeaseCredential:e.runtimeLeaseCredential,scopedDeliveryKey:this.options.scopedDeliveryKey,...t?{executionGrant:t}:{}}}async invoke(e,t){try{return await e()}catch(e){if(e instanceof HarnessProtocolError)throw harnessFailure(e,t);throw e}}}export function decodeRuntimeBrokerDelivery(e){if(!isDelivery(e))throw new RuntimeMessageChannelProtocolError("Message Service returned an invalid runtime delivery");return e}export function decodeRuntimeOperationHistory(e,t){if(!isHistory(e,t))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid operation history");return e}export function decodeNativePromptOperationHistory(e,t){const r=retainedVerifiedNativePrompt(t);if(!(r&&record(e)&&envelope(e.request)&&"runtime_rpc_request"===e.request.type&&void 0===e.request.in_reply_to&&e.request.message_id===r.request.requestMessageId&&e.request.channel_id===r.request.operationId&&isDeepStrictEqual(e.request.payload,r.request)&&isHistory(e,r.request.operationId,e.request)))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid native prompt operation history");if(void 0!==e.runBoundary&&!validNativeRunObservation(e.runBoundary,r))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid native run audit");return e}function validNativeRunObservation(e,t){if(!record(e))return!1;const r=t.params,n=t.request,o=["operationId","requestMessageId","requestHash","conversationId","runtimeRunId","taskRequestMessageId","replyMessageId","historyGeneration"];if(o.some(t=>"string"!=typeof e[t])||Object.keys(e).some(e=>![...o,"registration","finishedReceipt"].includes(e))||e.operationId!==n.operationId||e.requestMessageId!==n.requestMessageId||e.requestHash!==n.requestHash||e.conversationId!==r.conversationId||e.runtimeRunId!==r.runtimeRunId||e.taskRequestMessageId!==r.taskRequestMessageId||e.replyMessageId!==r.replyMessageId||e.historyGeneration!==t.historyGeneration)return!1;const i=(e,t)=>{if(!record(e)||e.activeRunRegistrationId!==r.taskId||!["active","finished"].includes(e.state)||t&&"finished"!==e.state||Object.keys(e).some(e=>!["activeRunRegistrationId","state","terminalState","source","replyState","replyStopReason","replyUpdatedAt","finishedAt"].includes(e)))return!1;if("active"===e.state)return 2===Object.keys(e).length;const n=e=>"string"==typeof e&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/.test(e)&&Date.parse(e)>0,o=e=>{const t=e.match(/\.(\d{1,9})/)?.[1]??"";return 1000000n*BigInt(Date.parse(e))+BigInt(t.padEnd(9,"0").slice(3))};return["completed","failed","cancelled"].includes(e.terminalState)&&["runtime","recovery"].includes(e.source)&&["completed","failed","refused","cancelled"].includes(e.replyState)&&("refused"===e.replyState?"failed":e.replyState)===e.terminalState&&"string"==typeof e.replyStopReason&&e.replyStopReason.length>0&&n(e.replyUpdatedAt)&&n(e.finishedAt)&&o(e.finishedAt)>=o(e.replyUpdatedAt)};return(void 0===e.registration||i(e.registration,!1))&&(void 0===e.finishedReceipt||i(e.finishedReceipt,!0))}export function decodeRuntimeAppendMessage(e,t){if(!envelope(e))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid append result");const r="runtime_rpc_response"===t.type?t.payload.requestMessageId:void 0;if(e.channel_id!==t.operationId||e.type!==t.type||e.in_reply_to!==r||!semanticEqual(e.payload,t.payload))throw new RuntimeMessageChannelProtocolError("Message Service append response correlation mismatch");return e}function appendResult(e){if(!record(e)||"persisted"!==e.status||"created"!==e.disposition&&"reused"!==e.disposition||!envelope(e.message))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid append result");return{disposition:e.disposition,message:e.message}}function harnessFailure(e,t){let r;if(e.body)try{r=JSON.parse(e.body)}catch{r=void 0}const n=record(r)&&"string"==typeof r.code?r.code:void 0,o=record(r)&&"string"==typeof r.message?r.message:t;return new RuntimeMessageChannelProtocolError(`${o} (${e.status})`,e.status,n)}function record(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}function strings(e){return Array.isArray(e)&&e.every(e=>"string"==typeof e)}function sameIds(e,t){return e.length===t.length&&[...e].sort().every((e,r)=>e===[...t].sort()[r])}function exactIdPartition(e,...t){return new Set(e).size===e.length&&!t.some(e=>new Set(e).size!==e.length)&&sameIds(t.flat(),e)}function envelope(e){return!!record(e)&&("string"==typeof e.message_id&&Number.isInteger(e.offset)&&e.offset>=1&&"string"==typeof e.channel_id&&(void 0===e.in_reply_to||"string"==typeof e.in_reply_to)&&["runtime_rpc_request","runtime_operation_started","runtime_operation_progress","runtime_effect_committed","runtime_projection_pending","runtime_projection_synced","runtime_projection_blocked","runtime_rpc_response","runtime_operation_cancel_requested"].includes(e.type)&&record(e.payload)&&"string"==typeof e.publisher_id&&"string"==typeof e.idempotency_key&&"string"==typeof e.created_at&&"completed"===e.state)}function isDelivery(e){return record(e)&&"string"==typeof e.deliveryId&&"boolean"==typeof e.redelivered&&Number.isInteger(e.idleMs)&&e.idleMs>=0&&envelope(e.message)&&(void 0===e.executionGrant||"string"==typeof e.executionGrant&&/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(e.executionGrant))&&["runtime_rpc_request","runtime_operation_cancel_requested"].includes(e.message.type)}function isHistory(e,t,r){if(!record(e))return!1;if(!(1===e.schemaVersion&&"string"==typeof e.operationId&&e.operationId===t&&"string"==typeof e.requestMessageId&&"string"==typeof e.requestHash&&["queued","running","runtime_committed","projection_pending","projection_blocked","succeeded","failed","cancelled","expired","outcome_unknown"].includes(e.status)&&["","committed"].includes(e.effectState)&&"boolean"==typeof e.terminal&&["none","final_message","deadline"].includes(e.terminalSource)&&"boolean"==typeof e.cancelRequested&&["","reserved","pending","synced","blocked","not_applicable"].includes(e.projectionState)&&Array.isArray(e.messages)&&e.messages.every(envelope)&&Number.isInteger(e.latestOffset)&&!(e.latestOffset<1)))return!1;const n=r?{ok:!0,envelope:r}:validateRuntimeRequestEnvelope(e.request);if(!n.ok||e.request.channel_id!==e.operationId||n.envelope.payload.operationId!==e.operationId||n.envelope.payload.requestMessageId!==e.requestMessageId||n.envelope.payload.requestHash!==e.requestHash)return!1;const o=n.envelope.payload;if(void 0!==e.started&&!correlatedEnvelope(e.started,"runtime_operation_started",o,["schemaVersion","operationId","requestMessageId","requestHash","executionGrantHash","handlerIdentity","dispatchEpoch","method","executionMode","claimedAt"]))return!1;if(void 0!==e.latestProgress&&!correlatedEnvelope(e.latestProgress,"runtime_operation_progress",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","phase","progress"]))return!1;if(!(void 0===e.effectCommitted||correlatedEnvelope(e.effectCommitted,"runtime_effect_committed",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","effectRecord","effectRecordHash","committedAt"])&&validEffectCommitted(e.effectCommitted.payload,o)))return!1;if(void 0!==e.projectionPending&&!correlatedEnvelope(e.projectionPending,"runtime_projection_pending",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","revision"]))return!1;if(void 0!==e.projectionSynced&&!correlatedEnvelope(e.projectionSynced,"runtime_projection_synced",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","revision"]))return!1;if(void 0!==e.projectionBlocked&&!correlatedEnvelope(e.projectionBlocked,"runtime_projection_blocked",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","revision","errorCode"]))return!1;if(void 0!==e.cancel){const t=validateRuntimeCancelEnvelope(e.cancel);if(!t.ok||!sameCorrelation(t.envelope,o))return!1}if(void 0!==e.final&&!correlatedEnvelope(e.final,"runtime_rpc_response",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","outcome","response","completedAt"]))return!1;const i=e.messages;if(0===i.length||e.latestOffset!==i.length||i.some((t,r)=>t.offset!==r+1||t.channel_id!==e.operationId)||!semanticEqual(i[0],e.request)||!historyMessagesMatchSummaries(i,e)||!projectionStateMatches(e))return!1;if(e.terminal!==("none"!==e.terminalSource)||"committed"===e.effectState!=(void 0!==e.effectCommitted)||void 0!==e.effectCommitted&&void 0===e.started||"queued"===e.status&&(void 0!==e.started||void 0!==e.effectCommitted)||["running","runtime_committed","projection_pending","projection_blocked"].includes(e.status)&&void 0===e.started)return!1;if("none"===e.terminalSource)return void 0===e.final&&["queued","running","runtime_committed","projection_pending","projection_blocked"].includes(e.status);if("deadline"===e.terminalSource)return void 0===e.final&&(void 0===e.started?"expired"===e.status:"outcome_unknown"===e.status);if(!envelope(e.final))return!1;const s=e.final.payload.outcome,a="succeeded"===s?"succeeded":"cancelled"===s?"cancelled":"expired"===s?"expired":"outcome_unknown"===s?"outcome_unknown":"projection_blocked"===s?"projection_blocked":"failed"===s?"failed":void 0;return e.status===a}function validEffectCommitted(e,t){const r=e.effectRecord;return!!(record(r)&&1===r.schemaVersion&&r.operationId===t.operationId&&r.method===t.method&&"string"==typeof r.coreResultRef&&0!==r.coreResultRef.length&&"string"==typeof r.coreResultHash&&/^[0-9a-f]{64}$/.test(r.coreResultHash)&&(void 0===r.projectionRevision||"string"==typeof r.projectionRevision&&/^(0|[1-9][0-9]*)$/.test(r.projectionRevision))&&"string"==typeof e.effectRecordHash&&/^[0-9a-f]{64}$/.test(e.effectRecordHash)&&runtimeMessageHash(RUNTIME_HASH_DOMAINS.effectRecord,r)===e.effectRecordHash&&"string"==typeof e.committedAt&&Number.isFinite(Date.parse(e.committedAt)))}function projectionStateMatches(e){const t=e.effectCommitted?.payload?.effectRecord?.projectionRevision,r="deadline"===e.terminalSource,n=e=>record(e)&&record(e.payload)&&e.payload.revision===t;switch(e.projectionState){case"":return void 0===e.effectCommitted&&void 0===e.projectionPending&&void 0===e.projectionSynced&&void 0===e.projectionBlocked&&(r||["queued","running","succeeded","failed","cancelled","expired","outcome_unknown"].includes(e.status));case"not_applicable":return void 0!==e.effectCommitted&&void 0===t&&void 0===e.projectionPending&&void 0===e.projectionSynced&&void 0===e.projectionBlocked&&(r||["runtime_committed","succeeded","outcome_unknown"].includes(e.status));case"reserved":return void 0!==e.effectCommitted&&void 0!==t&&void 0===e.projectionPending&&void 0===e.projectionSynced&&void 0===e.projectionBlocked&&(r||"runtime_committed"===e.status);case"pending":return void 0!==t&&n(e.projectionPending)&&void 0===e.projectionSynced&&void 0===e.projectionBlocked&&(r||"projection_pending"===e.status);case"synced":return void 0!==t&&n(e.projectionPending)&&n(e.projectionSynced)&&void 0===e.projectionBlocked&&(r||["runtime_committed","succeeded"].includes(e.status));case"blocked":return void 0!==t&&n(e.projectionPending)&&void 0===e.projectionSynced&&n(e.projectionBlocked)&&(r||"projection_blocked"===e.status);default:return!1}}function historyMessagesMatchSummaries(e,t){const r=t=>e.filter(e=>e.type===t),n=(e,t,n=1)=>{const o=r(e);return o.length<=n&&(void 0===t?0===o.length:o.length>0&&semanticEqual(t,o.at(-1)))};if(!(n("runtime_rpc_request",t.request)&&n("runtime_operation_started",t.started)&&n("runtime_effect_committed",t.effectCommitted)&&n("runtime_projection_pending",t.projectionPending)&&n("runtime_projection_synced",t.projectionSynced)&&n("runtime_projection_blocked",t.projectionBlocked)&&n("runtime_operation_cancel_requested",t.cancel)&&n("runtime_rpc_response",t.final)))return!1;const o=r("runtime_operation_progress");if(void 0===t.latestProgress?0!==o.length:0===o.length||!semanticEqual(t.latestProgress,o.at(-1)))return!1;if(t.cancelRequested!==(void 0!==t.cancel))return!1;const i=e.findIndex(e=>"runtime_rpc_response"===e.type);return-1===i||i===e.length-1}function correlatedEnvelope(e,t,r,n){const o="runtime_rpc_response"===t?r.requestMessageId:void 0;return!(!envelope(e)||e.type!==t||!hasKeys(e.payload,n)||e.in_reply_to!==o)&&sameCorrelation(e,r)}function sameCorrelation(e,t){const r=e.payload;return e.channel_id===t.operationId&&r.operationId===t.operationId&&r.requestMessageId===t.requestMessageId&&r.requestHash===t.requestHash&&r.dispatchEpoch===t.dispatchEpoch&&r.method===t.method}function hasKeys(e,t){return t.every(t=>void 0!==e[t])}
1
+ import{retainedCentralNativeRequest}from"./central-native-response.js";import{RUNTIME_HASH_DOMAINS}from"@beeos-ai/beeos-types/runtime";import{HarnessProtocolError,RuntimeMessagePlane}from"@beeos-ai/cloud-harness-sdk";import{isDeepStrictEqual}from"node:util";import{runtimeLeaseHttp}from"./message-service-runtime-authenticated-fetch.js";import{retainedVerifiedNativePrompt}from"./native-prompt-authority.js";import{runtimeMessageHash,semanticEqual,validateRuntimeCancelEnvelope,validateRuntimeRequestEnvelope}from"./runtime-message-channel-contract.js";export class RuntimeMessageChannelProtocolError extends Error{status;code;constructor(e,t,r){super(e),this.status=t,this.code=r,this.name="RuntimeMessageChannelProtocolError"}}export class MessageServiceRuntimeMessageChannel{options;plane;constructor(e){if(this.options=e,!e.scopedDeliveryKey)throw new Error("Message runtime delivery credential is required");this.plane=new RuntimeMessagePlane(runtimeLeaseHttp(e.serviceUrl,(t,r)=>e.transport.fetchBounded(t,r)))}async read(e){const t=await this.invoke(()=>this.plane.readDeliveries(this.credential(e.lease),{maxCount:e.maxCount,blockMs:e.blockMs},e.signal),"runtime delivery read failed");if(!record(t)||"deliveries"!==t.status||!Array.isArray(t.deliveries)||t.deliveries.length>e.maxCount||!t.deliveries.every(isDelivery)||new Set(t.deliveries.map(e=>e.deliveryId)).size!==t.deliveries.length)throw new RuntimeMessageChannelProtocolError("Message Service returned invalid runtime deliveries");return t.deliveries}async renew(e){const t=await this.invoke(()=>this.plane.renewDeliveries(this.credential(e.lease),e.deliveryIds),"runtime delivery renew failed");if(!(record(t)&&"renewed"===t.status&&strings(t.renewed)&&strings(t.notPending)&&exactIdPartition(e.deliveryIds,t.renewed,t.notPending)))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid delivery renewal");return{renewed:t.renewed,notPending:t.notPending}}async acknowledge(e){const t=await this.invoke(()=>this.plane.ackDeliveries(this.credential(e.lease),e.deliveryIds),"runtime delivery ack failed");if(!record(t)||"acknowledged"!==t.status||!strings(t.deliveryIds)||!sameIds(t.deliveryIds,e.deliveryIds))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid delivery acknowledgement")}async history(e){let t;try{t=await this.plane.operationHistory(this.credential(e.lease),e.operationId)}catch(e){if(!(e instanceof HarnessProtocolError))throw e;if(404===e.status)return{status:"not_found"};if(410===e.status)return{status:"expired"};throw harnessFailure(e,"runtime history read failed")}if(!isHistory(t,e.operationId))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid operation history");return{status:"found",snapshot:t}}async append(e){const t=appendResult(await this.invoke(()=>this.plane.appendOperationMessage(this.credential(e.lease,e.executionGrant),e.operationId,{type:e.type,payload:e.payload}),"runtime message-channel append failed")),r="runtime_rpc_response"===e.type?e.payload.requestMessageId:void 0;if(t.message.channel_id!==e.operationId||t.message.type!==e.type||t.message.in_reply_to!==r||!semanticEqual(t.message.payload,e.payload))throw new RuntimeMessageChannelProtocolError("Message Service append response correlation mismatch");return t}credential(e,t){return{runtimeLeaseCredential:e.runtimeLeaseCredential,scopedDeliveryKey:this.options.scopedDeliveryKey,...t?{executionGrant:t}:{}}}async invoke(e,t){try{return await e()}catch(e){if(e instanceof HarnessProtocolError)throw harnessFailure(e,t);throw e}}}export function decodeRuntimeBrokerDelivery(e){if(!isDelivery(e))throw new RuntimeMessageChannelProtocolError("Message Service returned an invalid runtime delivery");return e}export function decodeRuntimeOperationHistory(e,t){if(!isHistory(e,t))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid operation history");return e}export function decodeNativePromptOperationHistory(e,t){const r=retainedVerifiedNativePrompt(t);if(!(r&&record(e)&&envelope(e.request)&&"runtime_rpc_request"===e.request.type&&void 0===e.request.in_reply_to&&e.request.message_id===r.request.requestMessageId&&e.request.channel_id===r.request.operationId&&isDeepStrictEqual(e.request.payload,r.request)&&isHistory(e,r.request.operationId,e.request)))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid native prompt operation history");if(void 0!==e.runBoundary&&!validNativeRunObservation(e.runBoundary,r))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid native run audit");return e}export function decodeCentralNativeOperationHistory(e,t){const r=retainedCentralNativeRequest(t),n=record(e)&&envelope(e.request)?e.request.payload:null,o=e=>Object.fromEntries(Object.entries(e).filter(([e])=>!["executionGrantHash","claimDeadlineAt","createdAt"].includes(e)));if(!r||!record(e)||!envelope(e.request)||"runtime_rpc_request"!==e.request.type||void 0!==e.request.in_reply_to||e.request.message_id!==r.requestMessageId||e.request.channel_id!==r.operationId||!n||!isDeepStrictEqual(o(n),o(r))||"string"!=typeof n.executionGrantHash||!/^[a-f0-9]{64}$/.test(n.executionGrantHash)||![n.claimDeadlineAt,n.createdAt].every(e=>"string"==typeof e&&Number.isFinite(Date.parse(e)))||Date.parse(n.createdAt)>Date.parse(n.claimDeadlineAt)||Date.parse(n.claimDeadlineAt)>Date.parse(r.executionDeadlineAt)||void 0!==e.runBoundary||!isHistory(e,r.operationId,e.request))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid central native operation history");return e}function validNativeRunObservation(e,t){if(!record(e))return!1;const r=t.params,n=t.request,o=["operationId","requestMessageId","requestHash","conversationId","runtimeRunId","taskRequestMessageId","replyMessageId","historyGeneration"];if(o.some(t=>"string"!=typeof e[t])||Object.keys(e).some(e=>![...o,"registration","finishedReceipt"].includes(e))||e.operationId!==n.operationId||e.requestMessageId!==n.requestMessageId||e.requestHash!==n.requestHash||e.conversationId!==r.conversationId||e.runtimeRunId!==r.runtimeRunId||e.taskRequestMessageId!==r.taskRequestMessageId||e.replyMessageId!==r.replyMessageId||e.historyGeneration!==t.historyGeneration)return!1;const i=(e,t)=>{if(!record(e)||e.activeRunRegistrationId!==r.taskId||!["active","finished"].includes(e.state)||t&&"finished"!==e.state||Object.keys(e).some(e=>!["activeRunRegistrationId","state","terminalState","source","replyState","replyStopReason","replyUpdatedAt","finishedAt"].includes(e)))return!1;if("active"===e.state)return 2===Object.keys(e).length;const n=e=>"string"==typeof e&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/.test(e)&&Date.parse(e)>0,o=e=>{const t=e.match(/\.(\d{1,9})/)?.[1]??"";return 1000000n*BigInt(Date.parse(e))+BigInt(t.padEnd(9,"0").slice(3))};return["completed","failed","cancelled"].includes(e.terminalState)&&["runtime","recovery"].includes(e.source)&&["completed","failed","refused","cancelled"].includes(e.replyState)&&("refused"===e.replyState?"failed":e.replyState)===e.terminalState&&"string"==typeof e.replyStopReason&&e.replyStopReason.length>0&&n(e.replyUpdatedAt)&&n(e.finishedAt)&&o(e.finishedAt)>=o(e.replyUpdatedAt)};return(void 0===e.registration||i(e.registration,!1))&&(void 0===e.finishedReceipt||i(e.finishedReceipt,!0))}export function decodeRuntimeAppendMessage(e,t){if(!envelope(e))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid append result");const r="runtime_rpc_response"===t.type?t.payload.requestMessageId:void 0;if(e.channel_id!==t.operationId||e.type!==t.type||e.in_reply_to!==r||!semanticEqual(e.payload,t.payload))throw new RuntimeMessageChannelProtocolError("Message Service append response correlation mismatch");return e}function appendResult(e){if(!record(e)||"persisted"!==e.status||"created"!==e.disposition&&"reused"!==e.disposition||!envelope(e.message))throw new RuntimeMessageChannelProtocolError("Message Service returned invalid append result");return{disposition:e.disposition,message:e.message}}function harnessFailure(e,t){let r;if(e.body)try{r=JSON.parse(e.body)}catch{r=void 0}const n=record(r)&&"string"==typeof r.code?r.code:void 0,o=record(r)&&"string"==typeof r.message?r.message:t;return new RuntimeMessageChannelProtocolError(`${o} (${e.status})`,e.status,n)}function record(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}function strings(e){return Array.isArray(e)&&e.every(e=>"string"==typeof e)}function sameIds(e,t){return e.length===t.length&&[...e].sort().every((e,r)=>e===[...t].sort()[r])}function exactIdPartition(e,...t){return new Set(e).size===e.length&&!t.some(e=>new Set(e).size!==e.length)&&sameIds(t.flat(),e)}function envelope(e){return!!record(e)&&("string"==typeof e.message_id&&Number.isInteger(e.offset)&&e.offset>=1&&"string"==typeof e.channel_id&&(void 0===e.in_reply_to||"string"==typeof e.in_reply_to)&&["runtime_rpc_request","runtime_operation_started","runtime_operation_progress","runtime_effect_committed","runtime_projection_pending","runtime_projection_synced","runtime_projection_blocked","runtime_rpc_response","runtime_operation_cancel_requested"].includes(e.type)&&record(e.payload)&&"string"==typeof e.publisher_id&&"string"==typeof e.idempotency_key&&"string"==typeof e.created_at&&"completed"===e.state)}function isDelivery(e){return record(e)&&"string"==typeof e.deliveryId&&"boolean"==typeof e.redelivered&&Number.isInteger(e.idleMs)&&e.idleMs>=0&&envelope(e.message)&&(void 0===e.executionGrant||"string"==typeof e.executionGrant&&/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(e.executionGrant))&&["runtime_rpc_request","runtime_operation_cancel_requested"].includes(e.message.type)}function isHistory(e,t,r){if(!record(e))return!1;if(!(1===e.schemaVersion&&"string"==typeof e.operationId&&e.operationId===t&&"string"==typeof e.requestMessageId&&"string"==typeof e.requestHash&&["queued","running","runtime_committed","projection_pending","projection_blocked","succeeded","failed","cancelled","expired","outcome_unknown"].includes(e.status)&&["","committed"].includes(e.effectState)&&"boolean"==typeof e.terminal&&["none","final_message","deadline"].includes(e.terminalSource)&&"boolean"==typeof e.cancelRequested&&["","reserved","pending","synced","blocked","not_applicable"].includes(e.projectionState)&&Array.isArray(e.messages)&&e.messages.every(envelope)&&Number.isInteger(e.latestOffset)&&!(e.latestOffset<1)))return!1;const n=r?{ok:!0,envelope:r}:validateRuntimeRequestEnvelope(e.request);if(!n.ok||e.request.channel_id!==e.operationId||n.envelope.payload.operationId!==e.operationId||n.envelope.payload.requestMessageId!==e.requestMessageId||n.envelope.payload.requestHash!==e.requestHash)return!1;const o=n.envelope.payload;if(void 0!==e.started&&!correlatedEnvelope(e.started,"runtime_operation_started",o,["schemaVersion","operationId","requestMessageId","requestHash","executionGrantHash","handlerIdentity","dispatchEpoch","method","executionMode","claimedAt"]))return!1;if(void 0!==e.latestProgress&&!correlatedEnvelope(e.latestProgress,"runtime_operation_progress",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","phase","progress"]))return!1;if(!(void 0===e.effectCommitted||correlatedEnvelope(e.effectCommitted,"runtime_effect_committed",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","effectRecord","effectRecordHash","committedAt"])&&validEffectCommitted(e.effectCommitted.payload,o)))return!1;if(void 0!==e.projectionPending&&!correlatedEnvelope(e.projectionPending,"runtime_projection_pending",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","revision"]))return!1;if(void 0!==e.projectionSynced&&!correlatedEnvelope(e.projectionSynced,"runtime_projection_synced",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","revision"]))return!1;if(void 0!==e.projectionBlocked&&!correlatedEnvelope(e.projectionBlocked,"runtime_projection_blocked",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","revision","errorCode"]))return!1;if(void 0!==e.cancel){const t=validateRuntimeCancelEnvelope(e.cancel);if(!t.ok||!sameCorrelation(t.envelope,o))return!1}if(void 0!==e.final&&!correlatedEnvelope(e.final,"runtime_rpc_response",o,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","outcome","response","completedAt"]))return!1;const i=e.messages;if(0===i.length||e.latestOffset!==i.length||i.some((t,r)=>t.offset!==r+1||t.channel_id!==e.operationId)||!semanticEqual(i[0],e.request)||!historyMessagesMatchSummaries(i,e)||!projectionStateMatches(e))return!1;if(e.terminal!==("none"!==e.terminalSource)||"committed"===e.effectState!=(void 0!==e.effectCommitted)||void 0!==e.effectCommitted&&void 0===e.started||"queued"===e.status&&(void 0!==e.started||void 0!==e.effectCommitted)||["running","runtime_committed","projection_pending","projection_blocked"].includes(e.status)&&void 0===e.started)return!1;if("none"===e.terminalSource)return void 0===e.final&&["queued","running","runtime_committed","projection_pending","projection_blocked"].includes(e.status);if("deadline"===e.terminalSource)return void 0===e.final&&(void 0===e.started?"expired"===e.status:"outcome_unknown"===e.status);if(!envelope(e.final))return!1;const s=e.final.payload.outcome,a="succeeded"===s?"succeeded":"cancelled"===s?"cancelled":"expired"===s?"expired":"outcome_unknown"===s?"outcome_unknown":"projection_blocked"===s?"projection_blocked":"failed"===s?"failed":void 0;return e.status===a}function validEffectCommitted(e,t){const r=e.effectRecord;return!!(record(r)&&1===r.schemaVersion&&r.operationId===t.operationId&&r.method===t.method&&"string"==typeof r.coreResultRef&&0!==r.coreResultRef.length&&"string"==typeof r.coreResultHash&&/^[0-9a-f]{64}$/.test(r.coreResultHash)&&(void 0===r.projectionRevision||"string"==typeof r.projectionRevision&&/^(0|[1-9][0-9]*)$/.test(r.projectionRevision))&&"string"==typeof e.effectRecordHash&&/^[0-9a-f]{64}$/.test(e.effectRecordHash)&&runtimeMessageHash(RUNTIME_HASH_DOMAINS.effectRecord,r)===e.effectRecordHash&&"string"==typeof e.committedAt&&Number.isFinite(Date.parse(e.committedAt)))}function projectionStateMatches(e){const t=e.effectCommitted?.payload?.effectRecord?.projectionRevision,r="deadline"===e.terminalSource,n=e=>record(e)&&record(e.payload)&&e.payload.revision===t;switch(e.projectionState){case"":return void 0===e.effectCommitted&&void 0===e.projectionPending&&void 0===e.projectionSynced&&void 0===e.projectionBlocked&&(r||["queued","running","succeeded","failed","cancelled","expired","outcome_unknown"].includes(e.status));case"not_applicable":return void 0!==e.effectCommitted&&void 0===t&&void 0===e.projectionPending&&void 0===e.projectionSynced&&void 0===e.projectionBlocked&&(r||["runtime_committed","succeeded","outcome_unknown"].includes(e.status));case"reserved":return void 0!==e.effectCommitted&&void 0!==t&&void 0===e.projectionPending&&void 0===e.projectionSynced&&void 0===e.projectionBlocked&&(r||"runtime_committed"===e.status);case"pending":return void 0!==t&&n(e.projectionPending)&&void 0===e.projectionSynced&&void 0===e.projectionBlocked&&(r||"projection_pending"===e.status);case"synced":return void 0!==t&&n(e.projectionPending)&&n(e.projectionSynced)&&void 0===e.projectionBlocked&&(r||["runtime_committed","succeeded"].includes(e.status));case"blocked":return void 0!==t&&n(e.projectionPending)&&void 0===e.projectionSynced&&n(e.projectionBlocked)&&(r||"projection_blocked"===e.status);default:return!1}}function historyMessagesMatchSummaries(e,t){const r=t=>e.filter(e=>e.type===t),n=(e,t,n=1)=>{const o=r(e);return o.length<=n&&(void 0===t?0===o.length:o.length>0&&semanticEqual(t,o.at(-1)))};if(!(n("runtime_rpc_request",t.request)&&n("runtime_operation_started",t.started)&&n("runtime_effect_committed",t.effectCommitted)&&n("runtime_projection_pending",t.projectionPending)&&n("runtime_projection_synced",t.projectionSynced)&&n("runtime_projection_blocked",t.projectionBlocked)&&n("runtime_operation_cancel_requested",t.cancel)&&n("runtime_rpc_response",t.final)))return!1;const o=r("runtime_operation_progress");if(void 0===t.latestProgress?0!==o.length:0===o.length||!semanticEqual(t.latestProgress,o.at(-1)))return!1;if(t.cancelRequested!==(void 0!==t.cancel))return!1;const i=e.findIndex(e=>"runtime_rpc_response"===e.type);return-1===i||i===e.length-1}function correlatedEnvelope(e,t,r,n){const o="runtime_rpc_response"===t?r.requestMessageId:void 0;return!(!envelope(e)||e.type!==t||!hasKeys(e.payload,n)||e.in_reply_to!==o)&&sameCorrelation(e,r)}function sameCorrelation(e,t){const r=e.payload;return e.channel_id===t.operationId&&r.operationId===t.operationId&&r.requestMessageId===t.requestMessageId&&r.requestHash===t.requestHash&&r.dispatchEpoch===t.dispatchEpoch&&r.method===t.method}function hasKeys(e,t){return t.every(t=>void 0!==e[t])}
@@ -1 +1 @@
1
- import{CloudGatewayGrantJwksVerifier,GatewayGrantJwksVerifier}from"@beeos-ai/cloud-harness-sdk";import{MsRuntimeMessageChannelAdapter}from"./ms-runtime-message-channel-adapter.js";import{decodeRuntimeAppendMessage,decodeRuntimeBrokerDelivery,decodeRuntimeOperationHistory,decodeNativePromptOperationHistory,RuntimeMessageChannelProtocolError}from"./message-service-runtime-message-channel.js";import{isCanonicalSessionNewDelivery,SessionNewRuntimeDeliveryBridge}from"./session-new-runtime-delivery-bridge.js";import{NativeCloudPromptBridge}from"./native-cloud-prompt-bridge.js";import{CentralNativeResponse,isCentralNativeResponse}from"./central-native-response.js";export class MsRuntimeMessageChannelConsumerFactory{deps;constructor(e){if(this.deps=e,Boolean(e.client)===Boolean(e.runtimeDelivery))throw new Error("exactly one runtime delivery owner is required");if(e.runtimeDelivery&&!(e.verifier instanceof CloudGatewayGrantJwksVerifier))throw new Error("runtime delivery owner and grant realm differ")}async create(e){let t;const r=new SdkRuntimeMessageChannel(()=>{if(!t)throw new Error("SDK runtime delivery consumer is not attached");return t}),n=this.deps.centralPrompt&&this.deps.verifier instanceof CloudGatewayGrantJwksVerifier?new CentralNativeResponse({...this.deps.centralPrompt,verifier:this.deps.verifier,journal:this.deps.journal,getLease:()=>e.getLease()}):void 0,i=new MsRuntimeMessageChannelAdapter(e.dispatcher,r,this.deps.verifier,this.deps.ports,this.deps.journal,()=>e.getLease(),{...this.deps.options,allowedMethods:this.deps.allowedMethods,...n?{centralPromptBridge:n}:{},...this.deps.nativePrompt&&this.deps.verifier instanceof CloudGatewayGrantJwksVerifier?{nativePromptBridge:new NativeCloudPromptBridge({...this.deps.nativePrompt,verifier:this.deps.verifier,channel:r,journal:this.deps.journal,getLease:()=>e.getLease(),getLineage:()=>{const t=e.getBinding?.()??e.binding;return{journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}}})}:{},journalStoreId:e.binding.journalStoreId,journalGeneration:e.binding.journalGeneration,...e.getBinding?{getJournalLineage:()=>{const t=e.getBinding();return{journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}}}:{}}),s=this.deps.client&&this.deps.verifier instanceof GatewayGrantJwksVerifier?legacySessionNewConversationCreator(this.deps.client):this.deps.runtimeDelivery&&this.deps.verifier instanceof CloudGatewayGrantJwksVerifier?this.deps.sessionNewConversation:void 0,o=s?new SessionNewRuntimeDeliveryBridge({conversations:s,consumer:()=>{if(!t)throw new Error("SDK runtime delivery consumer is not attached");return t},verifier:this.deps.verifier,getLease:()=>e.getLease(),createRuntimeSession:e.createRuntimeSession,poison:async(e,t,r)=>{await i.acceptPoisonDelivery(e,t,r)}}):void 0,a=this.deps.client?.methods??this.deps.runtimeDelivery;if(!a)throw new Error("runtime delivery owner is unavailable");return t=a.consume({onDelivery:async(t,r)=>{runtimeDeliveryTrace(t);let s="fence";try{const a=currentFencedLease(e,r.lease);s="decode";if(isCentralNativeResponse(t)&&!n)throw new Error("central native Response startup composition is unavailable");const d=t,l=this.deps.nativePrompt&&2===d.message?.payload?.schemaVersion&&"session/prompt"===d.message.payload.method?t:decodeRuntimeBrokerDelivery(t);if(s="dispatch",isCanonicalSessionNewDelivery(l))return o?void await o.acceptDelivery(l,a,r.signal):void await i.acceptPoisonDelivery(l,"cloud_session_new_unsupported",a);await i.acceptDelivery(l,a,r.signal)}catch(e){runtimeDeliveryError(e);throw e}},onError:this.deps.options.onDeliveryError,readCount:this.deps.options.readCount,blockMs:this.deps.options.blockMs,idleDelayMs:this.deps.options.idleDelayMs,renewIntervalMs:this.deps.options.renewIntervalMs}),i.attachExternalDeliveryOwner(t),i}}export class SdkRuntimeMessageChannel{consumer;constructor(e){this.consumer=e}async read(){throw new Error("MessageClient owns runtime delivery reads")}async renew(){throw new Error("MessageClient owns runtime delivery renewal")}async acknowledge(e){assertLeaseAvailable(e.lease),await this.consumer().acknowledge(e.deliveryIds)}async history(e){assertLeaseAvailable(e.lease);const t=await this.consumer().history(e.operationId);return"found"!==t.status?t:{status:"found",snapshot:this.decodeHistory(t.snapshot,e)}}async append(e){assertLeaseAvailable(e.lease);const t=await this.consumer().append(e.operationId,e.type,e.payload,e.executionGrant);if("created"===t.outcome||"duplicate"===t.outcome)return{disposition:"created"===t.outcome?"created":"reused",message:decodeRuntimeAppendMessage(t.message,e)};if(t.history){const r=findReconciledMessage(this.decodeHistory(t.history,e),e);if(r)return{disposition:"reused",message:r}}throw new RuntimeMessageChannelProtocolError("runtime append outcome is unknown after history reconcile",503,"OUTCOME_UNKNOWN")}decodeHistory(e,t){if(!t.currentNativePrompt)return decodeRuntimeOperationHistory(e,t.operationId);if(t.currentNativePrompt.request.operationId!==t.operationId)throw new RuntimeMessageChannelProtocolError("native history operation does not match current proof");return decodeNativePromptOperationHistory(e,t.currentNativePrompt)}}function currentFencedLease(e,t){const r=e.getLease(),n=e.getBinding?.()??e.binding;if(!r||r.instanceId!==t.instanceId||r.handlerIdentity!==t.handlerIdentity||r.runtimeEpoch!==t.runtimeEpoch||r.leaseId!==t.leaseId||n.journalStoreId!==t.journalStoreId||n.journalGeneration!==t.journalGeneration)throw new Error("runtime delivery lease fence changed");if(Date.parse(r.leaseExpiresAt)<=Date.now())throw new Error("runtime delivery lease expired");return r}function assertLeaseAvailable(e){if(!Number.isFinite(Date.parse(e.leaseExpiresAt))||Date.parse(e.leaseExpiresAt)<=Date.now())throw new Error("runtime delivery lease expired")}function legacySessionNewConversationCreator(e){return{async create(t){const r=t.platformAgentId.startsWith("agent:")?t.platformAgentId:`agent:${t.platformAgentId}`;return{conversationId:(await e.conversations.create({agentId:t.platformAgentId,participants:dedupe([t.runtimeInstanceId,r,t.callerIdentityId??""]),...t.title?{title:t.title}:{},metadata:{source:"session/new",runtimeSessionId:t.runtimeSessionId,runtimeSessionKey:t.runtimeSessionKey,runtimeInstanceId:t.runtimeInstanceId,runtimeEpoch:t.runtimeEpoch,platformAgentId:t.platformAgentId},idempotencyKey:t.operationId})).id}}}}function dedupe(e){return[...new Set(e.filter(e=>e.length>0))]}function safeRuntimeDeliveryId(e){return"string"==typeof e&&e.length>0&&e.length<=256&&!/[\u0000-\u001f\u007f]/.test(e)?JSON.stringify(e):JSON.stringify("unavailable")}function safeRuntimeDeliveryCode(e){return"string"==typeof e&&/^[A-Za-z0-9_.:-]{1,64}$/.test(e)?e:"unavailable"}function runtimeDeliveryTrace(e){const t=null!==e&&"object"==typeof e?e:{};return{channelId:safeRuntimeDeliveryId((null!==t.message&&"object"==typeof t.message?t.message:{}).channel_id),deliveryId:safeRuntimeDeliveryId(t.deliveryId)}}function runtimeDeliveryError(e){const t=null!==e&&"object"==typeof e?e:{};return{code:safeRuntimeDeliveryCode(t.code),status:"number"==typeof t.status&&Number.isInteger(t.status)&&t.status>=100&&t.status<=599?String(t.status):"unavailable"}}function findReconciledMessage(e,t){for(let r=e.messages.length-1;r>=0;r-=1)try{return decodeRuntimeAppendMessage(e.messages[r],t)}catch{}}
1
+ import{CloudGatewayGrantJwksVerifier,GatewayGrantJwksVerifier}from"@beeos-ai/cloud-harness-sdk";import{MsRuntimeMessageChannelAdapter}from"./ms-runtime-message-channel-adapter.js";import{decodeRuntimeAppendMessage,decodeRuntimeBrokerDelivery,decodeRuntimeOperationHistory,decodeNativePromptOperationHistory,decodeCentralNativeOperationHistory,RuntimeMessageChannelProtocolError}from"./message-service-runtime-message-channel.js";import{isCanonicalSessionNewDelivery,SessionNewRuntimeDeliveryBridge}from"./session-new-runtime-delivery-bridge.js";import{NativeCloudPromptBridge}from"./native-cloud-prompt-bridge.js";import{CentralNativeResponse,isCentralNativeResponse}from"./central-native-response.js";export class MsRuntimeMessageChannelConsumerFactory{deps;constructor(e){if(this.deps=e,Boolean(e.client)===Boolean(e.runtimeDelivery))throw new Error("exactly one runtime delivery owner is required");if(e.runtimeDelivery&&!(e.verifier instanceof CloudGatewayGrantJwksVerifier))throw new Error("runtime delivery owner and grant realm differ")}async create(e){let t;const r=new SdkRuntimeMessageChannel(()=>{if(!t)throw new Error("SDK runtime delivery consumer is not attached");return t}),n=this.deps.centralPrompt&&this.deps.verifier instanceof CloudGatewayGrantJwksVerifier?new CentralNativeResponse({...this.deps.centralPrompt,verifier:this.deps.verifier,journal:this.deps.journal,channel:r,getLease:()=>e.getLease()}):void 0,i=new MsRuntimeMessageChannelAdapter(e.dispatcher,r,this.deps.verifier,this.deps.ports,this.deps.journal,()=>e.getLease(),{...this.deps.options,allowedMethods:this.deps.allowedMethods,...n?{centralPromptBridge:n}:{},...this.deps.nativePrompt&&this.deps.verifier instanceof CloudGatewayGrantJwksVerifier?{nativePromptBridge:new NativeCloudPromptBridge({...this.deps.nativePrompt,verifier:this.deps.verifier,channel:r,journal:this.deps.journal,getLease:()=>e.getLease(),getLineage:()=>{const t=e.getBinding?.()??e.binding;return{journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}}})}:{},journalStoreId:e.binding.journalStoreId,journalGeneration:e.binding.journalGeneration,...e.getBinding?{getJournalLineage:()=>{const t=e.getBinding();return{journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}}}:{}}),s=this.deps.client&&this.deps.verifier instanceof GatewayGrantJwksVerifier?legacySessionNewConversationCreator(this.deps.client):this.deps.runtimeDelivery&&this.deps.verifier instanceof CloudGatewayGrantJwksVerifier?this.deps.sessionNewConversation:void 0,o=s?new SessionNewRuntimeDeliveryBridge({conversations:s,consumer:()=>{if(!t)throw new Error("SDK runtime delivery consumer is not attached");return t},verifier:this.deps.verifier,getLease:()=>e.getLease(),createRuntimeSession:e.createRuntimeSession,poison:async(e,t,r)=>{await i.acceptPoisonDelivery(e,t,r)}}):void 0,a=this.deps.client?.methods??this.deps.runtimeDelivery;if(!a)throw new Error("runtime delivery owner is unavailable");return t=a.consume({onDelivery:async(t,r)=>{runtimeDeliveryTrace(t);let s="fence";try{const a=currentFencedLease(e,r.lease);s="decode";if(isCentralNativeResponse(t)&&!n)throw new Error("central native Response startup composition is unavailable");const d=t,l=this.deps.nativePrompt&&2===d.message?.payload?.schemaVersion&&"session/prompt"===d.message.payload.method?t:decodeRuntimeBrokerDelivery(t);if(s="dispatch",isCanonicalSessionNewDelivery(l))return o?void await o.acceptDelivery(l,a,r.signal):void await i.acceptPoisonDelivery(l,"cloud_session_new_unsupported",a);await i.acceptDelivery(l,a,r.signal)}catch(e){runtimeDeliveryError(e);throw e}},onError:this.deps.options.onDeliveryError,readCount:this.deps.options.readCount,blockMs:this.deps.options.blockMs,idleDelayMs:this.deps.options.idleDelayMs,renewIntervalMs:this.deps.options.renewIntervalMs}),i.attachExternalDeliveryOwner(t),i}}export class SdkRuntimeMessageChannel{consumer;constructor(e){this.consumer=e}async read(){throw new Error("MessageClient owns runtime delivery reads")}async renew(){throw new Error("MessageClient owns runtime delivery renewal")}async acknowledge(e){assertLeaseAvailable(e.lease),await this.consumer().acknowledge(e.deliveryIds)}async history(e){assertLeaseAvailable(e.lease);const t=await this.consumer().history(e.operationId);return"found"!==t.status?t:{status:"found",snapshot:this.decodeHistory(t.snapshot,e)}}async append(e){assertLeaseAvailable(e.lease);const t=await this.consumer().append(e.operationId,e.type,e.payload,e.executionGrant);if("created"===t.outcome||"duplicate"===t.outcome)return{disposition:"created"===t.outcome?"created":"reused",message:decodeRuntimeAppendMessage(t.message,e)};if(t.history){const r=this.decodeHistory(t.history,e);if(e.currentCentralIntent&&(r.terminal||r.cancelRequested))throw new RuntimeMessageChannelProtocolError("central native start history is closed",409,"authority_rejected");const n=findReconciledMessage(r,e);if(n)return{disposition:"reused",message:n}}throw new RuntimeMessageChannelProtocolError("runtime append outcome is unknown after history reconcile",503,"OUTCOME_UNKNOWN")}decodeHistory(e,t){if(t.currentCentralIntent){if(t.currentCentralIntent.request.operationId!==t.operationId)throw new RuntimeMessageChannelProtocolError("central native history operation changed");return decodeCentralNativeOperationHistory(e,t.currentCentralIntent)}if(!t.currentNativePrompt)return decodeRuntimeOperationHistory(e,t.operationId);if(t.currentNativePrompt.request.operationId!==t.operationId)throw new RuntimeMessageChannelProtocolError("native history operation does not match current proof");return decodeNativePromptOperationHistory(e,t.currentNativePrompt)}}function currentFencedLease(e,t){const r=e.getLease(),n=e.getBinding?.()??e.binding;if(!r||r.instanceId!==t.instanceId||r.handlerIdentity!==t.handlerIdentity||r.runtimeEpoch!==t.runtimeEpoch||r.leaseId!==t.leaseId||n.journalStoreId!==t.journalStoreId||n.journalGeneration!==t.journalGeneration)throw new Error("runtime delivery lease fence changed");if(Date.parse(r.leaseExpiresAt)<=Date.now())throw new Error("runtime delivery lease expired");return r}function assertLeaseAvailable(e){if(!Number.isFinite(Date.parse(e.leaseExpiresAt))||Date.parse(e.leaseExpiresAt)<=Date.now())throw new Error("runtime delivery lease expired")}function legacySessionNewConversationCreator(e){return{async create(t){const r=t.platformAgentId.startsWith("agent:")?t.platformAgentId:`agent:${t.platformAgentId}`;return{conversationId:(await e.conversations.create({agentId:t.platformAgentId,participants:dedupe([t.runtimeInstanceId,r,t.callerIdentityId??""]),...t.title?{title:t.title}:{},metadata:{source:"session/new",runtimeSessionId:t.runtimeSessionId,runtimeSessionKey:t.runtimeSessionKey,runtimeInstanceId:t.runtimeInstanceId,runtimeEpoch:t.runtimeEpoch,platformAgentId:t.platformAgentId},idempotencyKey:t.operationId})).id}}}}function dedupe(e){return[...new Set(e.filter(e=>e.length>0))]}function safeRuntimeDeliveryId(e){return"string"==typeof e&&e.length>0&&e.length<=256&&!/[\u0000-\u001f\u007f]/.test(e)?JSON.stringify(e):JSON.stringify("unavailable")}function safeRuntimeDeliveryCode(e){return"string"==typeof e&&/^[A-Za-z0-9_.:-]{1,64}$/.test(e)?e:"unavailable"}function runtimeDeliveryTrace(e){const t=null!==e&&"object"==typeof e?e:{};return{channelId:safeRuntimeDeliveryId((null!==t.message&&"object"==typeof t.message?t.message:{}).channel_id),deliveryId:safeRuntimeDeliveryId(t.deliveryId)}}function runtimeDeliveryError(e){const t=null!==e&&"object"==typeof e?e:{};return{code:safeRuntimeDeliveryCode(t.code),status:"number"==typeof t.status&&Number.isInteger(t.status)&&t.status>=100&&t.status<=599?String(t.status):"unavailable"}}function findReconciledMessage(e,t){for(let r=e.messages.length-1;r>=0;r-=1)try{return decodeRuntimeAppendMessage(e.messages[r],t)}catch{}}
@@ -1 +1 @@
1
- import{HtmlDeliveryGuard}from"../canvas/html-delivery.js";import{createNativeOutputFileAttempt}from"./native-output-file-attempt.js";import{downloadNativeInputFile}from"./native-input-files.js";import{bindExistingRuntimeChatReply}from"@beeos-ai/cloud-harness-sdk";import{RUNTIME_HASH_DOMAINS}from"@beeos-ai/beeos-types/runtime";import{dispatchImInboundPrompt}from"../im-runtime-dispatch.js";import{prepareNativePromptInput}from"./native-prompt-preflight.js";import{verifyNativePromptAuthority}from"./native-prompt-authority.js";import{RuntimeCommandError}from"./runtime-command-dispatcher.js";import{runtimeCommandResultHash}from"./runtime-command-journal.js";import{runtimeMessageBase,runtimeMessageHash,semanticEqual}from"./runtime-message-channel-contract.js";import{openClawSessionModePatch}from"./runtime-session-control-service.js";export const nativePromptCancellationReason="chat_cancel:runtime_operation_cancel_requested";export const nativePromptExecutionDeadlineReason="deadline exceeded: the Cloud turn execution budget is about to expire";const nativePromptWrapUpMarginMs=3e4;export class NativeCloudPromptBridge{options;constructor(e){if(this.options=e,"function"!=typeof e.host.resolveNativePromptSessionKey)throw new RuntimeCommandError("INVALID_PARAMS","native Core target resolver required");if("function"!=typeof e.host.prepareNativePromptModel)throw new RuntimeCommandError("INVALID_PARAMS","native Core model preparation required");if(!e.runBoundary)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run boundary required")}async execute(e){const{options:t}=this;if(await t.verifier.refresh(),!e.delivery.executionGrant)throw new RuntimeCommandError("INVALID_PARAMS","native grant missing");const a=e.delivery.message.payload,n="string"==typeof a.operationId?await t.journal.get(a.operationId):null,i=!!n&&"session.prompt"===n.command&&["started","effect_committed","projection_committed","failed"].includes(n.phase)&&n.paramsHash===a.paramsHash&&n.messageBinding?.requestMessageId===a.requestMessageId&&n.messageBinding?.requestHash===a.requestHash,r=verifyNativePromptAuthority({request:e.delivery.message.payload,decoded:t.verifier.verifyAndDecodeGrant(e.delivery.executionGrant),lease:e.lease,lineage:t.getLineage(),allowExpiredReadOnly:i}),{params:o}=r,s=r.request;try{const a=e.delivery.message;if("runtime_rpc_request"!==a.type||"completed"!==a.state||a.message_id!==s.requestMessageId||a.channel_id!==s.operationId||void 0!==a.in_reply_to)throw new RuntimeCommandError("INVALID_PARAMS","native envelope binding invalid");let n;void 0!==o.mode&&openClawSessionModePatch(o.mode);try{if(void 0!==o.mentions)throw new TypeError("native host per-prompt optional binding not implemented");n=prepareNativePromptInput(o.parts)}catch(e){throw new RuntimeCommandError(i?"OUTCOME_UNKNOWN":"INVALID_PARAMS","native host part unsupported",void 0,{cause:e})}const d=n.message;if(!t.host.activeRunAuthority)throw new RuntimeCommandError("EXECUTION_FAILED","native existing active-run authority unavailable");const m=()=>{const a=t.getLease(),n=t.getLineage();if(!a||a.instanceId!==e.lease.instanceId||a.handlerIdentity!==e.lease.handlerIdentity||a.runtimeEpoch!==o.runtimeLease.runtimeEpoch||a.leaseId!==o.runtimeLease.leaseId||n.journalStoreId!==o.runtimeLease.journalStoreId||n.journalGeneration!==o.runtimeLease.journalGeneration||Date.parse(a.leaseExpiresAt)<=Date.now())throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","native prompt attempt fenced")};m();const l=await t.channel.history({operationId:s.operationId,lease:e.lease,currentNativePrompt:r});if(m(),"found"!==l.status||l.snapshot.requestHash!==s.requestHash||l.snapshot.requestMessageId!==s.requestMessageId||!semanticEqual(l.snapshot.request.payload,s))throw new RuntimeCommandError("INVALID_PARAMS","native retained request mismatch");let u,p=await t.journal.get(s.operationId);if(m(),p&&("session.prompt"!==p.command||p.paramsHash!==s.paramsHash||p.runtimeEpoch!==o.runtimeLease.runtimeEpoch||p.messageBinding?.requestMessageId!==s.requestMessageId||p.messageBinding.requestHash!==s.requestHash))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native existing journal binding mismatch");if(!t.http.getMessage)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native task snapshot unavailable");try{u=await t.http.getMessage(t.getLease(),{conversationId:o.conversationId,messageId:o.taskRequestMessageId})}catch(e){throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original task snapshot unavailable",void 0,{cause:e})}if(m(),u.messageId!==o.taskRequestMessageId||u.conversationId!==o.conversationId||"chat_message"!==u.type||u.body!==d)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original task snapshot mismatch");const c=async()=>{if(!t.http.getMessage)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native single snapshot unavailable");m();const e=await t.http.getMessage(t.getLease(),{conversationId:o.conversationId,messageId:o.replyMessageId});return m(),this.assertReply(e,r),e};if(l.snapshot.started||p&&"prepared"!==p.phase){const e=l.snapshot.runBoundary?.finishedReceipt,a=l.snapshot.final;if(!(p&&["started","effect_committed","projection_committed","failed"].includes(p.phase)&&e&&"finished"===e.state&&e.activeRunRegistrationId===o.taskId&&a))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable MS finish audit or original result unavailable");const n=await c();if("agent_reply"!==n.type||n.state!==e.replyState||n.stopReason!==e.replyStopReason||n.updatedAt!==e.replyUpdatedAt)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original terminal does not match finished audit");const i=this.terminal(n,r);if(a.payload.outcome!==i.outcome||"final_message"!==l.snapshot.terminalSource)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final outcome mismatch");const d=a.payload.response;if("2.0"!==d.jsonrpc||d.id!==s.request.id)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final RPC binding mismatch");const u=runtimeCommandResultHash(i.result);if(p.resultReceipt&&p.resultReceipt.resultHash!==u||void 0!==p.result&&!semanticEqual(p.result,i.result))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original result conflicts with local receipt");if(void 0===d.result)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original canonical result evidence unavailable");{const e=l.snapshot.effectCommitted?.payload,t=runtimeMessageHash(RUNTIME_HASH_DOMAINS.coreResult,{method:s.method,result:d.result});if("succeeded"!==i.outcome||void 0!==d.error||!semanticEqual(d.result,i.result)||!e||e.effectRecord.coreResultHash!==t||e.effectRecord.coreResultRef!==`sha256:${t}`||a.payload.effectRecordHash!==e.effectRecordHash||a.payload.serviceResultHash!==runtimeMessageHash(RUNTIME_HASH_DOMAINS.serviceResult,{method:s.method,result:d.result}))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final result hash evidence mismatch")}const h=d.result;return m(),"started"===p.phase&&(p=await t.journal.transition({operationId:s.operationId,expectedRevision:p.revision,phase:"succeeded"===i.outcome?"effect_committed":"failed",result:h}),m()),{request:s,outcome:i.outcome,result:h,replayedFinal:a}}if(n.files.length&&!t.inputFiles)throw new RuntimeCommandError("EXECUTION_FAILED","native authorized input file resolver unavailable");if(l.snapshot.terminal||e.signal.aborted||l.snapshot.cancelRequested||await t.journal.getCancellation(s.operationId))throw new RuntimeCommandError("OPERATION_CANCELLED","native prompt cancelled before effect");const h=await t.host.resolveNativePromptSessionKey(r,m);if(m(),p=await t.journal.acceptMessageRequest({operationId:s.operationId,command:"session.prompt",paramsHash:s.paramsHash,runtimeEpoch:o.runtimeLease.runtimeEpoch,requestMessageId:s.requestMessageId,requestHash:s.requestHash}),m(),"prepared"!==p.phase)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native task already started");let v;const g=await bindExistingRuntimeChatReply({authority:{currentLease:t.getLease},http:t.http,binding:{conversationId:o.conversationId,messageId:o.replyMessageId,taskRequestMessageId:o.taskRequestMessageId,assertAttempt:m,assertPreparedClear:e=>{if(m(),!v||e.activeRunRegistrationId!==v||e.historyGeneration!==r.historyGeneration||e.runtimeEpoch!==o.runtimeLease.runtimeEpoch)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native prepared clear does not freeze this registered attempt")},mutationKey:e=>`native-reply:${s.operationId}:${o.runtimeLease.journalStoreId}:${o.runtimeLease.journalGeneration}:${e}`}});if(m(),e.signal.aborted||await t.journal.getCancellation(s.operationId))throw new RuntimeCommandError("OPERATION_CANCELLED","native prompt cancelled before start");await t.channel.append({operationId:s.operationId,lease:t.getLease(),currentNativePrompt:r,executionGrant:e.delivery.executionGrant,type:"runtime_operation_started",payload:{...runtimeMessageBase(s),executionGrantHash:s.executionGrantHash,handlerIdentity:e.lease.handlerIdentity,executionMode:"start",claimedAt:p.updatedAt}}),m(),p=await t.journal.transition({operationId:s.operationId,expectedRevision:p.revision,phase:"started"}),m();const I=()=>{m();const e=t.getLease();return{leaseId:e.leaseId,handlerIdentity:e.handlerIdentity,runtimeEpoch:e.runtimeEpoch,runtimeLeaseCredential:e.runtimeLeaseCredential}},f={operationId:s.operationId,requestMessageId:s.requestMessageId,conversationId:r.command.context.conversation.runtimeConversationUid,historyGeneration:r.historyGeneration,runtimeRunId:o.runtimeRunId},R=await t.runBoundary.start({...f,lease:I()});if(m(),"registered"!==R.status||R.historyGeneration!==r.historyGeneration||R.activeRunRegistrationId!==o.taskId)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run start did not register the original task");v=R.activeRunRegistrationId;const N=new AbortController,w=()=>N.abort(e.signal.reason);if(e.signal.addEventListener("abort",w,{once:!0}),e.signal.aborted&&w(),e.setCancel(e=>N.abort(e)),await t.journal.getCancellation(s.operationId)&&N.abort(nativePromptCancellationReason),m(),N.signal.aborted){if(e.signal.removeEventListener("abort",w),N.signal.reason===nativePromptCancellationReason)throw new RuntimeCommandError("OPERATION_CANCELLED","native prompt cancelled before host invocation");throw new RuntimeCommandError("OUTCOME_UNKNOWN","native registered run stopped before host invocation")}const E=[];let y;const C=JSON.parse((await g.opened()).rawText),O=C.parts?.length??0,M=async e=>{const t=await e;return m(),this.assertReply(t,r),y=t,t},_={id:g.id,get isTerminated(){return g.isTerminated},get parts(){return E},opened:async()=>({messageId:g.id,outcome:"bound"}),appendBody:e=>g.appendBody(e),setBody:e=>g.setBody(e),addPart:e=>{E.push(e),g.addPart(e)},replacePart:(e,t)=>{E[e]=t,g.replacePart(O+e,t)},appendToolResult:(e,t,a)=>{const n={type:"tool_result",tool_use_id:e,content:t,...a?{is_error:!0}:{}};E.push(n),g.addPart(n)},finalize:e=>M(g.finalize(e)),fail:e=>M(g.fail(e)),cancel:e=>M(g.cancel(e))},b={message:d,mediaPaths:[],mediaTypes:[]};let U,A;const q=t.host.htmlDeliveryEnabled?new HtmlDeliveryGuard(!1):void 0,T=createNativeOutputFileAttempt({htmlDelivery:q,operationId:s.operationId,requestMessageId:s.requestMessageId,paramsHash:s.paramsHash,activeRunRegistrationId:v,getLease:()=>(m(),t.getLease()),assertAttempt:m,signal:N.signal}),P=setTimeout(()=>N.abort(nativePromptExecutionDeadlineReason),Math.max(0,Math.min(Date.parse(s.executionDeadlineAt)-3e4-Date.now(),2147483647)));P.unref?.();try{await dispatchImInboundPrompt({...t.host,htmlDelivery:q,runtimeRunId:o.runtimeRunId,onNativeAgentRunStart:e=>T.bindHostRun(e),nativeActiveRunRegistration:{runtimeConversationUid:f.conversationId,runtimeSessionKey:r.command.context.conversation.runtimeSessionKey,historyGeneration:R.historyGeneration,targetMessageId:o.taskRequestMessageId,runtimeRunId:o.runtimeRunId,activeRunRegistrationId:R.activeRunRegistrationId},assertNativeTarget:async()=>{if(await t.host.resolveNativePromptSessionKey(r,m)!==h)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native prompt target changed before host invocation")},prepareNativeModel:async e=>{m(),await t.host.prepareNativePromptModel(r,e,m),m();for(const e of n.files){if(!t.inputFiles)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native authorized input file resolver unavailable");const a=await t.inputFiles.resolve({operationId:s.operationId,requestMessageId:s.requestMessageId,paramsHash:s.paramsHash,partIndex:e.partIndex,lease:t.getLease(),signal:N.signal});m();const n=await downloadNativeInputFile({fileId:e.fileId,...a,signal:N.signal,assertAttempt:m});b.mediaPaths.push(n.path),b.mediaTypes.push(n.mimeType)}m()},onNativeRunCompletion:e=>{A=e},retainedStream:_,abortSignal:N.signal,inReplyTo:o.taskRequestMessageId,prompt:{channelId:o.conversationId,inboundMessageId:o.taskRequestMessageId,requestId:s.requestMessageId,selfPrincipalId:e.lease.instanceId,sessionKey:h,dispatchInput:b},client:{messages:{startStream(){throw new Error("native reply POST forbidden")},getEnvelope:async()=>({state:(await c()).state})},getSnapshot:()=>({connection:"connected",messages:{},conversations:{}})}})}catch(e){U=e}finally{clearTimeout(P),T.close(),e.signal.removeEventListener("abort",w)}if(!A&&U)throw U;if(!A||A.runtimeRunId!==o.runtimeRunId||A.token.sessionKey!==h)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native physical host completion unavailable");let S;try{await A.completion}catch(e){S=e}if(m(),!y)throw new RuntimeCommandError("OUTCOME_UNKNOWN",void 0!==S?"native host/abort/drain did not converge":"native kernel settled without verified original reply terminal",void 0,{cause:S??U});const H=this.terminal(y,r),L=await c();g.assertTerminalSnapshot(L);const x="completed"===L.state?"completed":"cancelled"===L.state?"cancelled":"failed",K=await t.runBoundary.finish({...f,activeRunRegistrationId:v,terminalState:x,source:"runtime",lease:I()});if(m(),"finished"!==K.status&&"idempotent"!==K.status||K.activeRunRegistrationId!==v)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run finish was not acknowledged");return await t.journal.transition({operationId:s.operationId,expectedRevision:p.revision,phase:"succeeded"===H.outcome?"effect_committed":"failed",result:H.result}),m(),{request:s,...H}}catch(e){throw new NativePromptExecutionFailure(s,e)}}assertReply(e,t){if(e.messageId!==t.params.replyMessageId||e.conversationId!==t.params.conversationId||e.replyTo!==t.params.taskRequestMessageId)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable reply binding mismatch")}terminal(e,t){if(!e.stopReason||!["completed","failed","refused","cancelled"].includes(e.state))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable terminal absent");const a="cancelled"===e.state&&"user_stop"===e.stopReason?"cancelled":"completed"===e.state&&"end_turn"===e.stopReason?"succeeded":"failed";return{outcome:a,result:{runtimeRunId:t.params.runtimeRunId,stopReason:e.stopReason,requestAborted:"cancelled"===e.state&&"user_stop"===e.stopReason,..."failed"===a?{error:e.body}:{}}}}}export const NATIVE_PROMPT_UNKNOWN_REASONS=new Set(["native MS run boundary required","native existing journal binding mismatch","native task snapshot unavailable","native original task snapshot unavailable","native original task snapshot mismatch","native single snapshot unavailable","native durable MS finish audit or original result unavailable","native original terminal does not match finished audit","native original final outcome mismatch","native original final RPC binding mismatch","native original result conflicts with local receipt","native original final result hash evidence mismatch","native original canonical result evidence unavailable","native task already started","native prepared clear does not freeze this registered attempt","native MS run start did not register the original task","native registered run stopped before host invocation","native prompt target changed before host invocation","native authorized input file resolver unavailable","native physical host completion unavailable","native host/abort/drain did not converge","native kernel settled without verified original reply terminal","native MS run finish was not acknowledged","native durable reply binding mismatch","native durable terminal absent"]);export function nativePromptUnknownReason(e){return e instanceof RuntimeCommandError&&"OUTCOME_UNKNOWN"===e.code?NATIVE_PROMPT_UNKNOWN_REASONS.has(e.message)?e.message:"unlisted":"not_unknown"}export class NativePromptExecutionFailure extends Error{request;failure;constructor(e,t){super(t instanceof Error?t.message:String(t),{cause:t}),this.request=e,this.failure=t}}
1
+ import{HtmlDeliveryGuard}from"../canvas/html-delivery.js";import{createNativeOutputFileAttempt,registerNativeOutputRunContext}from"./native-output-file-attempt.js";import{downloadNativeInputFile}from"./native-input-files.js";import{bindExistingRuntimeChatReply}from"@beeos-ai/cloud-harness-sdk";import{RUNTIME_HASH_DOMAINS}from"@beeos-ai/beeos-types/runtime";import{dispatchImInboundPrompt}from"../im-runtime-dispatch.js";import{prepareNativePromptInput}from"./native-prompt-preflight.js";import{verifyNativePromptAuthority}from"./native-prompt-authority.js";import{RuntimeCommandError}from"./runtime-command-dispatcher.js";import{runtimeCommandResultHash}from"./runtime-command-journal.js";import{runtimeMessageBase,runtimeMessageHash,semanticEqual}from"./runtime-message-channel-contract.js";import{openClawSessionModePatch}from"./runtime-session-control-service.js";export const nativePromptCancellationReason="chat_cancel:runtime_operation_cancel_requested";export const nativePromptExecutionDeadlineReason="deadline exceeded: the Cloud turn execution budget is about to expire";const nativePromptWrapUpMarginMs=3e4;export class NativeCloudPromptBridge{options;constructor(e){if(this.options=e,"function"!=typeof e.host.resolveNativePromptSessionKey)throw new RuntimeCommandError("INVALID_PARAMS","native Core target resolver required");if("function"!=typeof e.host.prepareNativePromptModel)throw new RuntimeCommandError("INVALID_PARAMS","native Core model preparation required");if(!e.runBoundary)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run boundary required")}async execute(e){const{options:t}=this;if(await t.verifier.refresh(),!e.delivery.executionGrant)throw new RuntimeCommandError("INVALID_PARAMS","native grant missing");const a=e.delivery.message.payload,n="string"==typeof a.operationId?await t.journal.get(a.operationId):null,i=!!n&&"session.prompt"===n.command&&["started","effect_committed","projection_committed","failed"].includes(n.phase)&&n.paramsHash===a.paramsHash&&n.messageBinding?.requestMessageId===a.requestMessageId&&n.messageBinding?.requestHash===a.requestHash,r=verifyNativePromptAuthority({request:e.delivery.message.payload,decoded:t.verifier.verifyAndDecodeGrant(e.delivery.executionGrant),lease:e.lease,lineage:t.getLineage(),allowExpiredReadOnly:i}),{params:o}=r,s=r.request;try{const a=e.delivery.message;if("runtime_rpc_request"!==a.type||"completed"!==a.state||a.message_id!==s.requestMessageId||a.channel_id!==s.operationId||void 0!==a.in_reply_to)throw new RuntimeCommandError("INVALID_PARAMS","native envelope binding invalid");let n;void 0!==o.mode&&openClawSessionModePatch(o.mode);try{if(void 0!==o.mentions)throw new TypeError("native host per-prompt optional binding not implemented");n=prepareNativePromptInput(o.parts)}catch(e){throw new RuntimeCommandError(i?"OUTCOME_UNKNOWN":"INVALID_PARAMS","native host part unsupported",void 0,{cause:e})}const d=n.message;if(!t.host.activeRunAuthority)throw new RuntimeCommandError("EXECUTION_FAILED","native existing active-run authority unavailable");const m=()=>{const a=t.getLease(),n=t.getLineage();if(!a||a.instanceId!==e.lease.instanceId||a.handlerIdentity!==e.lease.handlerIdentity||a.runtimeEpoch!==o.runtimeLease.runtimeEpoch||a.leaseId!==o.runtimeLease.leaseId||n.journalStoreId!==o.runtimeLease.journalStoreId||n.journalGeneration!==o.runtimeLease.journalGeneration||Date.parse(a.leaseExpiresAt)<=Date.now())throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","native prompt attempt fenced")};m();const u=await t.channel.history({operationId:s.operationId,lease:e.lease,currentNativePrompt:r});if(m(),"found"!==u.status||u.snapshot.requestHash!==s.requestHash||u.snapshot.requestMessageId!==s.requestMessageId||!semanticEqual(u.snapshot.request.payload,s))throw new RuntimeCommandError("INVALID_PARAMS","native retained request mismatch");let l,p=await t.journal.get(s.operationId);if(m(),p&&("session.prompt"!==p.command||p.paramsHash!==s.paramsHash||p.runtimeEpoch!==o.runtimeLease.runtimeEpoch||p.messageBinding?.requestMessageId!==s.requestMessageId||p.messageBinding.requestHash!==s.requestHash))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native existing journal binding mismatch");if(!t.http.getMessage)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native task snapshot unavailable");try{l=await t.http.getMessage(t.getLease(),{conversationId:o.conversationId,messageId:o.taskRequestMessageId})}catch(e){throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original task snapshot unavailable",void 0,{cause:e})}if(m(),l.messageId!==o.taskRequestMessageId||l.conversationId!==o.conversationId||"chat_message"!==l.type||l.body!==d)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original task snapshot mismatch");const c=async()=>{if(!t.http.getMessage)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native single snapshot unavailable");m();const e=await t.http.getMessage(t.getLease(),{conversationId:o.conversationId,messageId:o.replyMessageId});return m(),this.assertReply(e,r),e};if(u.snapshot.started||p&&"prepared"!==p.phase){const e=u.snapshot.runBoundary?.finishedReceipt,a=u.snapshot.final;if(!(p&&["started","effect_committed","projection_committed","failed"].includes(p.phase)&&e&&"finished"===e.state&&e.activeRunRegistrationId===o.taskId&&a))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable MS finish audit or original result unavailable");const n=await c();if("agent_reply"!==n.type||n.state!==e.replyState||n.stopReason!==e.replyStopReason||n.updatedAt!==e.replyUpdatedAt)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original terminal does not match finished audit");const i=this.terminal(n,r);if(a.payload.outcome!==i.outcome||"final_message"!==u.snapshot.terminalSource)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final outcome mismatch");const d=a.payload.response;if("2.0"!==d.jsonrpc||d.id!==s.request.id)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final RPC binding mismatch");const l=runtimeCommandResultHash(i.result);if(p.resultReceipt&&p.resultReceipt.resultHash!==l||void 0!==p.result&&!semanticEqual(p.result,i.result))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original result conflicts with local receipt");if(void 0===d.result)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original canonical result evidence unavailable");{const e=u.snapshot.effectCommitted?.payload,t=runtimeMessageHash(RUNTIME_HASH_DOMAINS.coreResult,{method:s.method,result:d.result});if("succeeded"!==i.outcome||void 0!==d.error||!semanticEqual(d.result,i.result)||!e||e.effectRecord.coreResultHash!==t||e.effectRecord.coreResultRef!==`sha256:${t}`||a.payload.effectRecordHash!==e.effectRecordHash||a.payload.serviceResultHash!==runtimeMessageHash(RUNTIME_HASH_DOMAINS.serviceResult,{method:s.method,result:d.result}))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native original final result hash evidence mismatch")}const h=d.result;return m(),"started"===p.phase&&(p=await t.journal.transition({operationId:s.operationId,expectedRevision:p.revision,phase:"succeeded"===i.outcome?"effect_committed":"failed",result:h}),m()),{request:s,outcome:i.outcome,result:h,replayedFinal:a}}if(n.files.length&&!t.inputFiles)throw new RuntimeCommandError("EXECUTION_FAILED","native authorized input file resolver unavailable");if(u.snapshot.terminal||e.signal.aborted||u.snapshot.cancelRequested||await t.journal.getCancellation(s.operationId))throw new RuntimeCommandError("OPERATION_CANCELLED","native prompt cancelled before effect");const h=await t.host.resolveNativePromptSessionKey(r,m);if(m(),p=await t.journal.acceptMessageRequest({operationId:s.operationId,command:"session.prompt",paramsHash:s.paramsHash,runtimeEpoch:o.runtimeLease.runtimeEpoch,requestMessageId:s.requestMessageId,requestHash:s.requestHash}),m(),"prepared"!==p.phase)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native task already started");let v;const g=await bindExistingRuntimeChatReply({authority:{currentLease:t.getLease},http:t.http,binding:{conversationId:o.conversationId,messageId:o.replyMessageId,taskRequestMessageId:o.taskRequestMessageId,assertAttempt:m,assertPreparedClear:e=>{if(m(),!v||e.activeRunRegistrationId!==v||e.historyGeneration!==r.historyGeneration||e.runtimeEpoch!==o.runtimeLease.runtimeEpoch)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native prepared clear does not freeze this registered attempt")},mutationKey:e=>`native-reply:${s.operationId}:${o.runtimeLease.journalStoreId}:${o.runtimeLease.journalGeneration}:${e}`}});if(m(),e.signal.aborted||await t.journal.getCancellation(s.operationId))throw new RuntimeCommandError("OPERATION_CANCELLED","native prompt cancelled before start");await t.channel.append({operationId:s.operationId,lease:t.getLease(),currentNativePrompt:r,executionGrant:e.delivery.executionGrant,type:"runtime_operation_started",payload:{...runtimeMessageBase(s),executionGrantHash:s.executionGrantHash,handlerIdentity:e.lease.handlerIdentity,executionMode:"start",claimedAt:p.updatedAt}}),m(),p=await t.journal.transition({operationId:s.operationId,expectedRevision:p.revision,phase:"started"}),m();const I=()=>{m();const e=t.getLease();return{leaseId:e.leaseId,handlerIdentity:e.handlerIdentity,runtimeEpoch:e.runtimeEpoch,runtimeLeaseCredential:e.runtimeLeaseCredential}},f={operationId:s.operationId,requestMessageId:s.requestMessageId,conversationId:r.command.context.conversation.runtimeConversationUid,historyGeneration:r.historyGeneration,runtimeRunId:o.runtimeRunId},R=await t.runBoundary.start({...f,lease:I()});if(m(),"registered"!==R.status||R.historyGeneration!==r.historyGeneration||R.activeRunRegistrationId!==o.taskId)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run start did not register the original task");v=R.activeRunRegistrationId;const N=new AbortController,w=()=>N.abort(e.signal.reason);if(e.signal.addEventListener("abort",w,{once:!0}),e.signal.aborted&&w(),e.setCancel(e=>N.abort(e)),await t.journal.getCancellation(s.operationId)&&N.abort(nativePromptCancellationReason),m(),N.signal.aborted){if(e.signal.removeEventListener("abort",w),N.signal.reason===nativePromptCancellationReason)throw new RuntimeCommandError("OPERATION_CANCELLED","native prompt cancelled before host invocation");throw new RuntimeCommandError("OUTCOME_UNKNOWN","native registered run stopped before host invocation")}const y=[];let E;const C=JSON.parse((await g.opened()).rawText),O=C.parts?.length??0,M=async e=>{const t=await e;return m(),this.assertReply(t,r),E=t,t},_={id:g.id,get isTerminated(){return g.isTerminated},get parts(){return y},opened:async()=>({messageId:g.id,outcome:"bound"}),appendBody:e=>g.appendBody(e),setBody:e=>g.setBody(e),addPart:e=>{y.push(e),g.addPart(e)},replacePart:(e,t)=>{y[e]=t,g.replacePart(O+e,t)},appendToolResult:(e,t,a)=>{const n={type:"tool_result",tool_use_id:e,content:t,...a?{is_error:!0}:{}};y.push(n),g.addPart(n)},finalize:e=>M(g.finalize(e)),fail:e=>M(g.fail(e)),cancel:e=>M(g.cancel(e))},b={message:d,mediaPaths:[],mediaTypes:[]};let U,A;const q=t.host.htmlDeliveryEnabled?new HtmlDeliveryGuard(!1):void 0,T=createNativeOutputFileAttempt({htmlDelivery:q,sessionKey:h,operationId:s.operationId,requestMessageId:s.requestMessageId,paramsHash:s.paramsHash,activeRunRegistrationId:v,attemptId:v,getLease:()=>(m(),t.getLease()),assertAttempt:m,signal:N.signal}),P=registerNativeOutputRunContext({runId:o.runtimeRunId,sessionKey:h,operationId:s.operationId,activeRunRegistrationId:v,attemptId:v}),S=setTimeout(()=>N.abort(nativePromptExecutionDeadlineReason),Math.max(0,Math.min(Date.parse(s.executionDeadlineAt)-3e4-Date.now(),2147483647)));S.unref?.();try{await dispatchImInboundPrompt({...t.host,htmlDelivery:q,runtimeRunId:o.runtimeRunId,onNativeAgentRunStart:e=>T.bindHostRun(e),nativeActiveRunRegistration:{runtimeConversationUid:f.conversationId,runtimeSessionKey:r.command.context.conversation.runtimeSessionKey,historyGeneration:R.historyGeneration,targetMessageId:o.taskRequestMessageId,runtimeRunId:o.runtimeRunId,activeRunRegistrationId:R.activeRunRegistrationId},assertNativeTarget:async()=>{if(await t.host.resolveNativePromptSessionKey(r,m)!==h)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native prompt target changed before host invocation")},prepareNativeModel:async e=>{m(),await t.host.prepareNativePromptModel(r,e,m),m();for(const e of n.files){if(!t.inputFiles)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native authorized input file resolver unavailable");const a=await t.inputFiles.resolve({operationId:s.operationId,requestMessageId:s.requestMessageId,paramsHash:s.paramsHash,partIndex:e.partIndex,lease:t.getLease(),signal:N.signal});m();const n=await downloadNativeInputFile({fileId:e.fileId,...a,signal:N.signal,assertAttempt:m});b.mediaPaths.push(n.path),b.mediaTypes.push(n.mimeType)}m()},onNativeRunCompletion:e=>{A=e},retainedStream:_,abortSignal:N.signal,inReplyTo:o.taskRequestMessageId,prompt:{channelId:o.conversationId,inboundMessageId:o.taskRequestMessageId,requestId:s.requestMessageId,selfPrincipalId:e.lease.instanceId,sessionKey:h,dispatchInput:b},client:{messages:{startStream(){throw new Error("native reply POST forbidden")},getEnvelope:async()=>({state:(await c()).state})},getSnapshot:()=>({connection:"connected",messages:{},conversations:{}})}})}catch(e){U=e}finally{clearTimeout(S),T.close(),P(),e.signal.removeEventListener("abort",w)}if(!A&&U)throw U;if(!A||A.runtimeRunId!==o.runtimeRunId||A.token.sessionKey!==h)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native physical host completion unavailable");let x;try{await A.completion}catch(e){x=e}if(m(),!E)throw new RuntimeCommandError("OUTCOME_UNKNOWN",void 0!==x?"native host/abort/drain did not converge":"native kernel settled without verified original reply terminal",void 0,{cause:x??U});const H=this.terminal(E,r),L=await c();g.assertTerminalSnapshot(L);const K="completed"===L.state?"completed":"cancelled"===L.state?"cancelled":"failed",j=await t.runBoundary.finish({...f,activeRunRegistrationId:v,terminalState:K,source:"runtime",lease:I()});if(m(),"finished"!==j.status&&"idempotent"!==j.status||j.activeRunRegistrationId!==v)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native MS run finish was not acknowledged");return await t.journal.transition({operationId:s.operationId,expectedRevision:p.revision,phase:"succeeded"===H.outcome?"effect_committed":"failed",result:H.result}),m(),{request:s,...H}}catch(e){throw new NativePromptExecutionFailure(s,e)}}assertReply(e,t){if(e.messageId!==t.params.replyMessageId||e.conversationId!==t.params.conversationId||e.replyTo!==t.params.taskRequestMessageId)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable reply binding mismatch")}terminal(e,t){if(!e.stopReason||!["completed","failed","refused","cancelled"].includes(e.state))throw new RuntimeCommandError("OUTCOME_UNKNOWN","native durable terminal absent");const a="cancelled"===e.state&&"user_stop"===e.stopReason?"cancelled":"completed"===e.state&&"end_turn"===e.stopReason?"succeeded":"failed";return{outcome:a,result:{runtimeRunId:t.params.runtimeRunId,stopReason:e.stopReason,requestAborted:"cancelled"===e.state&&"user_stop"===e.stopReason,..."failed"===a?{error:e.body}:{}}}}}export const NATIVE_PROMPT_UNKNOWN_REASONS=new Set(["native MS run boundary required","native existing journal binding mismatch","native task snapshot unavailable","native original task snapshot unavailable","native original task snapshot mismatch","native single snapshot unavailable","native durable MS finish audit or original result unavailable","native original terminal does not match finished audit","native original final outcome mismatch","native original final RPC binding mismatch","native original result conflicts with local receipt","native original final result hash evidence mismatch","native original canonical result evidence unavailable","native task already started","native prepared clear does not freeze this registered attempt","native MS run start did not register the original task","native registered run stopped before host invocation","native prompt target changed before host invocation","native authorized input file resolver unavailable","native physical host completion unavailable","native host/abort/drain did not converge","native kernel settled without verified original reply terminal","native MS run finish was not acknowledged","native durable reply binding mismatch","native durable terminal absent"]);export function nativePromptUnknownReason(e){return e instanceof RuntimeCommandError&&"OUTCOME_UNKNOWN"===e.code?NATIVE_PROMPT_UNKNOWN_REASONS.has(e.message)?e.message:"unlisted":"not_unknown"}export class NativePromptExecutionFailure extends Error{request;failure;constructor(e,t){super(t instanceof Error?t.message:String(t),{cause:t}),this.request=e,this.failure=t}}
@@ -1 +1 @@
1
- const runs=new Map,tools=new Map,consumed=new Set;export function createNativeOutputFileAttempt(t){let e,o=!0;const s={...t,assertAttempt(){if(!o)throw new Error("native output file attempt finished");t.signal.throwIfAborted(),t.assertAttempt();const e=t.getLease();if(!e.runtimeLeaseCredential||!Number.isFinite(Date.parse(e.leaseExpiresAt))||Date.parse(e.leaseExpiresAt)<=Date.now())throw new Error("native output file lease fenced")},getLease:()=>(s.assertAttempt(),t.getLease())};return{bindHostRun(t){if(s.assertAttempt(),!t||void 0!==e||runs.has(t))throw new Error("native output file Host run binding ambiguous");e=t,runs.set(t,s)},close(){o=!1,e&&runs.get(e)===s&&runs.delete(e);for(const[t,e]of tools)e.assertAttempt===s.assertAttempt&&tools.delete(t);for(const e of consumed)e.startsWith(t.operationId+"\0")&&consumed.delete(e)}}}export function prepareNativeOutputTool(t,e){if(!t||!e)throw new Error("native output file trusted Host tool binding missing");const o=runs.get(t);if(!o)throw new Error("native output file trusted run missing");o.assertAttempt();const s=o.operationId+"\0"+e;if(tools.has(e)||consumed.has(s))throw new Error("native output file tool binding ambiguous or consumed");tools.set(e,{...o,toolCallId:e})}export function consumeNativeOutputTool(t){const e=tools.get(t);if(tools.delete(t),!e)throw new Error("native output file tool capability missing");return e.assertAttempt(),consumed.add(e.operationId+"\0"+t),e}export function nativeHtmlDeliveryForRun(t){const e=t?runs.get(t):void 0;if(e)return e.assertAttempt(),e.htmlDelivery}
1
+ export class NativeOutputToolBindingError extends Error{missing;constructor(t,e){super(t),this.missing=e,this.name="NativeOutputToolBindingError"}}const runs=new Map,sessions=new Map,tools=new Map,consumed=new Set,diagnostics=new Map,contextKey=(t,e)=>t+":"+e;export function registerNativeOutputRunContext(t){const e={operationId:t.operationId,activeRunRegistrationId:t.activeRunRegistrationId,...t.responseId?{responseId:t.responseId}:{},...t.attemptId?{attemptId:t.attemptId}:{}},s=[...t.runId?[contextKey("run",t.runId)]:[],...t.sessionKey?[contextKey("session",t.sessionKey)]:[]];for(const t of s)diagnostics.set(t,e);return()=>{for(const t of s)diagnostics.get(t)===e&&diagnostics.delete(t)}}export function nativeOutputBindingDiagnostic(t){const e=(t.runId?diagnostics.get(contextKey("run",t.runId)):void 0)??(t.sessionKey?diagnostics.get(contextKey("session",t.sessionKey)):void 0),s=t.error instanceof NativeOutputToolBindingError?[...t.error.missing]:["hostCapability"];return{response_id:e?.responseId??"unknown",operation_id:e?.operationId??"unknown",attempt_id:e?.attemptId??e?.activeRunRegistrationId??"unknown",run_id:t.runId??"missing",tool_call_id:t.toolCallId??"missing",session_key:t.sessionKey??"missing",missing:s,reason:t.error instanceof Error?t.error.message:"unknown"}}export function createNativeOutputFileAttempt(t){let e,s=!0;const o={...t,assertAttempt(){if(!s)throw new Error("native output file attempt finished");t.signal.throwIfAborted(),t.assertAttempt();const e=t.getLease();if(!e.runtimeLeaseCredential||!Number.isFinite(Date.parse(e.leaseExpiresAt))||Date.parse(e.leaseExpiresAt)<=Date.now())throw new Error("native output file lease fenced")},getLease:()=>(o.assertAttempt(),t.getLease())};return{bindHostRun(s){if(o.assertAttempt(),!s||void 0!==e||runs.has(s))throw new Error("native output file Host run binding ambiguous");const n=t.sessionKey;if(n&&sessions.has(n)&&sessions.get(n)!==o)throw new Error("native output file Host session binding ambiguous");e=s,runs.set(s,o),n&&sessions.set(n,o)},close(){s=!1,e&&runs.get(e)===o&&runs.delete(e),t.sessionKey&&sessions.get(t.sessionKey)===o&&sessions.delete(t.sessionKey);for(const[t,e]of tools)e.assertAttempt===o.assertAttempt&&tools.delete(t);for(const e of consumed)e.startsWith(t.operationId+"\0")&&consumed.delete(e)}}}export function prepareNativeOutputTool(t,e,s){if(!e)throw new NativeOutputToolBindingError("native output file trusted Host tool binding missing",["toolCallId"]);let o;if(t){if(o=runs.get(t),!o)throw new NativeOutputToolBindingError("native output file trusted run missing",["hostRunBinding"])}else{if(!s)throw new NativeOutputToolBindingError("native output file Host run binding missing",["runId"]);if(o=sessions.get(s),!o)throw new NativeOutputToolBindingError("native output file trusted session run missing",["sessionBinding"])}o.assertAttempt();const n=o.operationId+"\0"+e;if(tools.has(e)||consumed.has(n))throw new Error("native output file tool binding ambiguous or consumed");tools.set(e,{...o,toolCallId:e})}export function consumeNativeOutputTool(t){const e=tools.get(t);if(tools.delete(t),!e)throw new Error("native output file tool capability missing");return e.assertAttempt(),consumed.add(e.operationId+"\0"+t),e}export function nativeHtmlDeliveryForRun(t){const e=t?runs.get(t):void 0;if(e)return e.assertAttempt(),e.htmlDelivery}
@@ -1 +1 @@
1
- import{logChatLatency}from"../chat-latency.js";export const classifyCatalogSessionKey=o=>{if(!o)return"boot";if(o.includes(":beeos-conversation:"))return"im_conversation";const e=o.split(":");return 3===e.length&&"agent"===e[0]?"acp_uuid":"other"};const TOOL_HINT_KEYS=new Set(["description","parameters","schema","inputSchema","function"]),NESTED_INVENTORY_KEYS=["tools","groups","entries","items","catalog","result","payload","inventory","profiles"],toolRecordName=o=>"string"==typeof o.name&&o.name.length>0?o.name:"string"==typeof o.id&&o.id.length>0?o.id:"",looksLikeTool=o=>{if(!o||"object"!=typeof o||Array.isArray(o))return!1;const e=o;if(!toolRecordName(e))return!1;for(const o of TOOL_HINT_KEYS)if(void 0!==e[o])return!0;return!1},collectToolRecords=(o,e,t,s)=>{if(null==o||s>6)return;if("object"!=typeof o)return;if(t.has(o))return;if(t.add(o),looksLikeTool(o)){const t=o;if(!Array.isArray(t.tools)&&!Array.isArray(t.groups))return void e.push(o)}if(Array.isArray(o)){for(const r of o)collectToolRecords(r,e,t,s+1);return}const r=o;for(const o of NESTED_INVENTORY_KEYS)o in r&&collectToolRecords(r[o],e,t,s+1);if(!(e.length>0))for(const o of Object.values(r))collectToolRecords(o,e,t,s+1)};export const extractToolRecords=o=>{const e=[];return collectToolRecords(o,e,new Set,0),e};export const summarizeCatalogPayloadKeys=o=>null==o?"null":Array.isArray(o)?`array:${o.length}`:"object"!=typeof o?typeof o:Object.keys(o).slice(0,16).join(",");export const summarizeCatalogTools=(o,e=8)=>{const t=extractToolRecords(o).map(o=>{const e=JSON.stringify(o)??"";return{name:o&&"object"==typeof o&&toolRecordName(o)||"?",bytes:e.length}});return t.sort((o,e)=>e.bytes-o.bytes),{toolCount:t.length,catalogBytes:t.reduce((o,e)=>o+e.bytes,0),topTools:t.slice(0,e).map(o=>`${o.name}:${o.bytes}`).join(",")}};const resolveMode=(o,e)=>o||(e?"both":"catalog");export async function prepareOpenClawToolCatalog(o){const e=Date.now(),t=resolveMode(o.mode,o.sessionKey),s=o.keyKind??classifyCatalogSessionKey(o.sessionKey),r=[];try{let a,n;"catalog"!==t&&"both"!==t||(a=await o.request("tools.catalog",{agentId:o.agentId}),r.push("catalog")),"effective"!==t&&"both"!==t||!o.sessionKey||(n=await o.request("tools.effective",{agentId:o.agentId,sessionKey:o.sessionKey}),r.push("effective"));const l=a??n,c=void 0===l?void 0:summarizeCatalogTools(l);o.logger?.info?.(`[runtime-core] prepared tool catalog agent=${o.agentId}`+(o.sessionKey?` session=${o.sessionKey}`:"")+` key_kind=${s} mode=${t} elapsed_ms=`+(Date.now()-e)),o.logger&&logChatLatency(o.logger,"claw.catalog.prepare",s,e,{key_kind:s,mode:t,methods:r.join(","),...c?{tool_count:c.toolCount,catalog_bytes:c.catalogBytes,top_tools:c.topTools}:{},...c&&0===c.toolCount&&void 0!==l?{payload_keys:summarizeCatalogPayloadKeys(l)}:{}})}catch(e){o.logger?.warn?.(`[runtime-core] tool catalog prepare failed agent=${o.agentId}: ${e instanceof Error?e.message:String(e)}`)}}
1
+ import{logChatLatency}from"../chat-latency.js";export const classifyCatalogSessionKey=o=>{if(!o)return"boot";if(o.includes(":beeos-conversation:"))return"im_conversation";const e=o.split(":");return 3===e.length&&"agent"===e[0]?"acp_uuid":"other"};const TOOL_HINT_KEYS=new Set(["description","parameters","schema","inputSchema","function"]),NESTED_INVENTORY_KEYS=["tools","groups","entries","items","catalog","result","payload","inventory","profiles"],toolRecordName=o=>"string"==typeof o.name&&o.name.length>0?o.name:"string"==typeof o.id&&o.id.length>0?o.id:"",looksLikeTool=o=>{if(!o||"object"!=typeof o||Array.isArray(o))return!1;const e=o;if(!toolRecordName(e))return!1;for(const o of TOOL_HINT_KEYS)if(void 0!==e[o])return!0;return!1},collectToolRecords=(o,e,t,s)=>{if(null==o||s>6)return;if("object"!=typeof o)return;if(t.has(o))return;if(t.add(o),looksLikeTool(o)){const t=o;if(!Array.isArray(t.tools)&&!Array.isArray(t.groups))return void e.push(o)}if(Array.isArray(o)){for(const a of o)collectToolRecords(a,e,t,s+1);return}const a=o;for(const o of NESTED_INVENTORY_KEYS)o in a&&collectToolRecords(a[o],e,t,s+1);if(!(e.length>0))for(const o of Object.values(a))collectToolRecords(o,e,t,s+1)};export const extractToolRecords=o=>{const e=[];return collectToolRecords(o,e,new Set,0),e};export const summarizeCatalogPayloadKeys=o=>null==o?"null":Array.isArray(o)?`array:${o.length}`:"object"!=typeof o?typeof o:Object.keys(o).slice(0,16).join(",");export const summarizeCatalogTools=(o,e=8)=>{const t=extractToolRecords(o).map(o=>{const e=JSON.stringify(o)??"";return{name:o&&"object"==typeof o&&toolRecordName(o)||"?",bytes:e.length}});return t.sort((o,e)=>e.bytes-o.bytes),{toolCount:t.length,catalogBytes:t.reduce((o,e)=>o+e.bytes,0),topTools:t.slice(0,e).map(o=>`${o.name}:${o.bytes}`).join(",")}};const resolveMode=(o,e)=>o||(e?"both":"catalog");export async function prepareOpenClawToolCatalog(o){const e=Date.now(),t=resolveMode(o.mode,o.sessionKey),s=o.keyKind??classifyCatalogSessionKey(o.sessionKey),a=[];try{let r,n;"catalog"!==t&&"both"!==t||(r=await o.request("tools.catalog",{agentId:o.agentId}),a.push("catalog")),"effective"!==t&&"both"!==t||!o.sessionKey||(n=await o.request("tools.effective",{agentId:o.agentId,sessionKey:o.sessionKey}),a.push("effective"));const l=r??n,i=void 0===l?void 0:summarizeCatalogTools(l);o.logger?.info?.(`[runtime-core] prepared tool catalog agent=${o.agentId}`+(o.sessionKey?` session=${o.sessionKey}`:"")+` key_kind=${s} mode=${t} elapsed_ms=`+(Date.now()-e)),i&&0===i.toolCount&&void 0!==l&&o.logger?.warn?.(`[runtime-core] tool catalog is EMPTY agent=${o.agentId}`+(o.sessionKey?` session=${o.sessionKey}`:"")+` key_kind=${s} mode=${t}`+` payload_keys=${summarizeCatalogPayloadKeys(l)}; the model will see only tool_search/tool_call/tool_describe and every real tool call will fail with "Unknown tool id" — check the agent tool policy (openclaw.json tools.allow must not be an empty array)`),o.logger&&logChatLatency(o.logger,"claw.catalog.prepare",s,e,{key_kind:s,mode:t,methods:a.join(","),...i?{tool_count:i.toolCount,catalog_bytes:i.catalogBytes,top_tools:i.topTools}:{},...i&&0===i.toolCount&&void 0!==l?{payload_keys:summarizeCatalogPayloadKeys(l)}:{}})}catch(e){o.logger?.warn?.(`[runtime-core] tool catalog prepare failed agent=${o.agentId}: ${e instanceof Error?e.message:String(e)}`)}}
@@ -1 +1 @@
1
- import{createHash,timingSafeEqual}from"node:crypto";import{readFile}from"node:fs/promises";import{isDeepStrictEqual}from"node:util";import{centralNativeRuntime}from"./central-native-runtime.js";import{resolveSyncAgentName}from"../agent-sync.js";import{injectOpenClawCredentials}from"./sandbox-native-credentials.js";function unboundActivation(e){const{execution_binding_version:t,...i}=e;return{...i,request_hash:""}}let executionResolver;export function installSandboxNativeExecutionResolver(e){if(executionResolver)throw new Error("native original execution authority is already installed");executionResolver=e}export function createSandboxNativeTargetLookup(e,t){return async({localAgentId:i,activation:n})=>{const r=e(),a=r?.authorityLease,o=t();if(!r||!a?.runtimeLeaseCredential||Date.parse(a.leaseExpiresAt)<=Date.now()||a.instanceId!==n.sandbox_id||!o?.isConnected)throw new Error("current native target projection authority/catalog transport is unavailable");const s=await o.request("agents.list",{}),c=s.agents?.filter(e=>e.id===i)??[];if(1!==c.length)throw new Error("actual native target catalog entry is missing or ambiguous");if(resolveSyncAgentName(c[0])!==i)throw new Error("actual native catalog key differs from the current identity projection key");const l=await r.identities.resolveOrCreate(i),d=r.authorityLease;if(e()!==r||!d||Date.parse(d.leaseExpiresAt)<=Date.now()||d.instanceId!==a.instanceId||d.leaseId!==a.leaseId||d.runtimeEpoch!==a.runtimeEpoch||d.handlerIdentity!==a.handlerIdentity)throw new Error("native target projection authority changed during observation");return{runtimeAgentUid:l,runtimeLocalKey:i,runtimeEpoch:d.runtimeEpoch,leaseIdentity:JSON.stringify({instanceId:d.instanceId,leaseId:d.leaseId,runtimeEpoch:d.runtimeEpoch,handlerIdentity:d.handlerIdentity})}}}const object=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),sha256=e=>createHash("sha256").update(e).digest("hex"),ref=e=>`native:${sha256(JSON.stringify(e))}`,nonempty=e=>"string"==typeof e&&e.length>0,secretRef=e=>object(e)&&3===Object.keys(e).length&&("env"===e.source||"file"===e.source||"exec"===e.source)&&nonempty(e.provider)&&nonempty(e.id);export function containsApplied(e,t){return secretRef(t)?isDeepStrictEqual(e,t)||nonempty(e):Array.isArray(t)?Array.isArray(e)&&e.length===t.length&&t.every((t,i)=>containsApplied(e[i],t)):object(t)?object(e)&&Object.entries(t).every(([t,i])=>containsApplied(e[t],i)):isDeepStrictEqual(e,t)}export function sessionConfigObservation(e){const{activation:t,allocation:i,native:n,execution:r,receipt:a}=e,o=n.config_components;if(!(object(o)&&object(r.loadAuthority)&&Number.isSafeInteger(i.epoch)&&nonempty(t.resolved_request_hash)&&nonempty(t.central_read_watermark)))throw new Error("actual SessionConfigReceipt inputs (components/authority/allocation/selection) are unavailable");const s=structuredClone(r.loadAuthority),c=i.id,l=r.sessionKey,d={session_load_receipt:e.sessionLoadReceipt,prepared:a.receipt_id},u=ref({config:a.receipt_id,session:l,authority:s}),p={contractVersion:"1",revision:t.config_revision,manifestRef:{id:t.config_manifest.manifest_id,digest:t.config_sha256},appliedAt:a.prepared_at,sessionId:t.session_id,applyAt:"session_start",components:structuredClone(o),binding:{bindingId:t.binding_id,agentId:t.agent_id,harnessId:t.harness,sandboxId:t.sandbox_id,allocationId:i.id,allocationEpoch:i.epoch},applicationState:"applied",authority:s,hostInstanceId:c,nativeSessionId:l,receiptId:u,mutationScope:"session_private"};return{resolvedRequestHash:t.resolved_request_hash,readWatermark:t.central_read_watermark,admission:{attemptId:r.binding.attemptId,hostInstanceId:c,executionBindingVersion:t.execution_binding_version,nativeSessionId:l,nativeIncarnation:`${process.pid}@${i.boot_id}`,requestHash:t.request_hash},sessionConfigReceipt:{receiptId:u,commandId:t.command_id,authority:s,hostInstanceId:c,nativeSessionId:l,configuration:p,evidenceRef:{id:e.sessionLoadReceipt,digest:sha256(JSON.stringify(d))},preparedConfigReceiptId:a.receipt_id},loadedFacts:{loaded_model_id:null,actual_provider_id:null,actual_model_id:null,endpoint_ref:null,api_mode:null,reasoning:null,fallback_used:null,skills_digest:null,tool_schema_digest:null,credential_activation_revision:a.credential_activation_revision,components:[],memory_observation:"not_read",memory_read_watermark:null}}}export class SandboxNativeActivation{config;activeWriters;activationFile;targetLookup;reloadSecrets;logger;prepared;materialized;boundNativeRequestHash;targetAuthority;persona;credentialReceipt;reloadedCredentialsReceipt;control=Promise.resolve();serialize(e){const t=this.control.then(e,e);return this.control=t.catch(()=>{}),t}constructor(e,t,i,n,r,a){this.config=e,this.activeWriters=t,this.activationFile=i,this.targetLookup=n,this.reloadSecrets=r,this.logger=a}reloadSecretsAfterInjection(e){this.reloadSecrets&&this.reloadedCredentialsReceipt!==e&&(this.reloadedCredentialsReceipt=e,Promise.resolve().then(()=>this.reloadSecrets()).catch(e=>this.logger?.warn?.(`[beeos-claw] secrets reload after credential delivery failed: ${e instanceof Error?e.message:String(e)}`)))}prepare(e){return this.serialize(()=>this.apply(e))}target(e){return this.serialize(()=>this.apply(e,!0))}async assertEnvelope(e,t=!1){const i=JSON.parse(await readFile(this.activationFile,"utf8")),{activation:n,allocation:r,config_manifest:a}=e,o=!t&&"execution"===n.kind&&"execution"===i.activation?.kind&&""===i.activation.request_hash&&nonempty(n.request_hash)&&isDeepStrictEqual(unboundActivation(i.activation),unboundActivation(n));if(!isDeepStrictEqual(i.activation,n)&&!o||!isDeepStrictEqual(i.allocation,r)||!isDeepStrictEqual(i.config_manifest,a))throw new Error("native preparation does not match the current immutable activation");if(!nonempty(n.preparation_id)||!nonempty(r.id)||!nonempty(r.boot_id)||!Number.isFinite(Date.parse(n.deadline_at))||Date.parse(n.deadline_at)<=Date.now())throw new Error("native preparation authority/deadline is unavailable");if(!isDeepStrictEqual(JSON.parse(await readFile(e.config_manifest_path,"utf8")),a))throw new Error("native configuration bytes differ from the verified manifest");if("credential_activation"in a)throw new Error("private credential inputs must use transient authenticated delivery");if("central_chat"in a||"centralChat"in a)throw new Error("immutable native configuration must not contain per-execution chat authority")}credentials(e){return this.serialize(async()=>{if(await this.assertEnvelope(e),0!==this.activeWriters())throw new Error("native writers must drain before credential injection");if(this.materialized&&!this.credentialReceipt)throw new Error("credentials must be injected before native provider construction");const t=injectOpenClawCredentials({delivery:e.credential_delivery,activation:e.activation,allocation:e.allocation,previous:this.credentialReceipt,mcpCredentialSlots:e.config_manifest.mcp_credential_slots});return this.credentialReceipt=t,this.reloadSecretsAfterInjection(t.receipt_id),structuredClone(t)})}async apply(e,t=!1){await this.assertEnvelope(e,t);const{activation:i,allocation:n,config_manifest:r}=e;if(!this.credentialReceipt)throw new Error("actual native credential injection receipt is required, including empty credentials");if("execution"===i.kind){if(!nonempty(i.public_request_hash))throw new Error("original public request hash is required");if(t&&(""!==i.request_hash||void 0!==this.boundNativeRequestHash))throw new Error("target observation requires the original unbound native request hash");const e=i.execution_binding_version;if(t?void 0!==e&&0!==e:!(Number.isSafeInteger(e)&&e>=1))throw new Error("State execution binding version must be unbound at target and positive at Session load");if(!t&&(!nonempty(i.request_hash)||void 0!==this.boundNativeRequestHash&&this.boundNativeRequestHash!==i.request_hash))throw new Error("native canonical request hash is missing or changed")}const{execution_grant:a,credential_delivery:o,...s}=e,c={...s,activation:unboundActivation(i)};if(this.materialized&&!isDeepStrictEqual(this.materialized,c))throw new Error("a different native materialization requires a drained process restart");let l;if("execution"===i.kind&&!t){if(!nonempty(e.execution_grant)||!executionResolver)throw new Error("authenticated original canonical execution request producer is unavailable");if(l=await executionResolver(e),!this.targetAuthority||!this.targetLookup)throw new Error("the original work has no observed native target");const t=await this.targetLookup({localAgentId:r.local_agent_id,activation:i,allocation:n});if(!isDeepStrictEqual(t,this.targetAuthority))throw new Error("native target/current runtime lease changed before session load");if(l.nativeRequestHash!==i.request_hash||l.binding.sessionId!==i.session_id||l.binding.responseId!==i.response_id||l.binding.operationId!==i.operation_id||l.runtimeAgentUid!==this.targetAuthority.runtimeAgentUid||!l.sessionKey.startsWith(`agent:${r.local_agent_id}:`))throw new Error("original execution request differs from the current native activation");this.assertSelection(l.params,e)}if(!t&&this.prepared&&isDeepStrictEqual(this.prepared.envelope,s)){if(!isDeepStrictEqual(this.prepared.execution,l))throw new Error("original execution binding changed");return l&&await centralNativeRuntime().prepareReadOnly(l.sessionKey,l.binding),structuredClone(this.prepared.receipt)}if(0!==this.activeWriters())throw new Error("native writers must drain before applying configuration");if(!["configuration","credential_restart","execution"].includes(i.kind))throw new Error("unsupported native activation kind");if(1!==r.schema_version||!nonempty(r.local_agent_id)||!object(r.openclaw_config))throw new Error("resolved OpenClaw native configuration v1 is required");const d=r.mcp_credential_slots;if(void 0!==d&&(!Array.isArray(d)||d.some(e=>"string"!=typeof e||!/^[a-z][a-z0-9_]{0,63}$/.test(e)||"openai_api_key"===e)||new Set(d).size!==d.length))throw new Error("resolved MCP credential slots are invalid");const u=new Set(["agents","models","tools","skills","mcp"]);if(Object.keys(r.openclaw_config).some(e=>!u.has(e)))throw new Error("native config may only apply agent/model/tool/Skill/MCP settings");const p=r.openclaw_config.agents;if(!object(p)||!object(p.entries)||!object(p.entries[r.local_agent_id]))throw new Error("local_agent_id is not present in the resolved native agent catalog");if(this.prepared&&!isDeepStrictEqual(this.prepared.envelope,s))throw new Error("a different native activation requires a drained process restart");if(r.persona&&(!nonempty(r.persona.persona_id)||!nonempty(r.persona.revision)||!nonempty(r.persona.source_receipt_ref)||sha256(r.persona.content)!==r.persona.sha256))throw new Error("resolved Persona source/revision/content digest is invalid");if("execution"!==i.kind&&(i.session_id||i.response_id||i.execution_binding_version))throw new Error("non-execution preparation must not manufacture a Session or Response");if(t&&"execution"!==i.kind)throw new Error("target observation requires the original execution preparation");this.materialized||await this.config.mutateConfigFile({afterWrite:{mode:"auto"},mutate:e=>{for(const[t,i]of Object.entries(r.openclaw_config))e[t]=structuredClone(i)}});const h=this.config.current();if(!containsApplied(h,r.openclaw_config))throw new Error("native config has not been applied by OpenClaw");const f=h.agents;if(!object(f)||!object(f.entries)||!object(f.entries[r.local_agent_id]))throw new Error("local_agent_id is not present in the actual resolved native agent catalog");if(this.persona=r.persona?{localAgentId:r.local_agent_id,content:r.persona.content}:void 0,this.materialized=structuredClone(c),t){if(!this.targetLookup)throw new Error("actual native target identity producer is unavailable");const e=await this.targetLookup({localAgentId:r.local_agent_id,activation:i,allocation:n});if(!nonempty(e.runtimeAgentUid)||e.runtimeLocalKey!==r.local_agent_id||!/^[1-9][0-9]*$/.test(e.runtimeEpoch)||!nonempty(e.leaseIdentity))throw new Error("actual native catalog/identity projection does not match the applied target");return this.targetAuthority=structuredClone(e),{runtime_agent_uid:e.runtimeAgentUid,runtime_local_key:e.runtimeLocalKey,harness:"openclaw",config_digest:i.config_sha256,runtime_epoch:e.runtimeEpoch}}let g="";if("execution"===i.kind){if(!l)throw new Error("original central native execution authority is unavailable");this.boundNativeRequestHash=l.nativeRequestHash,await centralNativeRuntime().prepareReadOnly(l.sessionKey,l.binding),g=ref({session_key:l.sessionKey,binding:l.binding,source:centralNativeRuntime().source(l.sessionKey)})}const _=(new Date).toISOString(),v={preparation_id:i.preparation_id,kind:i.kind,binding_id:i.binding_id,config_revision:i.config_revision,config_sha256:i.config_sha256,target_intent_digest:i.target_intent_digest,authority_ref:i.authority_ref,config_manifest:i.config_manifest,credential_set_id:i.credential_set_id,credential_set_version:i.credential_set_version,credential_activation_revision:this.credentialReceipt.config.revision,receipt_scope:"configuration"===i.kind?"current_config":"activation",credential_activation_receipt_ref:this.credentialReceipt.receipt_id,host_instance_id:n.id,runtime_lineage_ref:n.boot_id,session_load_receipt_ref:g,prepared_at:_,..."execution"===i.kind?{execution_binding_version:i.execution_binding_version}:{},receipt_id:ref({activation:i,allocation:n,config:r.openclaw_config,persona:r.persona?.sha256??null,credential_receipt:this.credentialReceipt.receipt_id,sessionLoadReceipt:g})};return l&&centralNativeRuntime().bindExecutionObservation(l.binding,sessionConfigObservation({activation:i,allocation:n,native:r,execution:l,receipt:v,sessionLoadReceipt:g})),this.prepared={envelope:structuredClone(s),execution:l&&structuredClone(l),receipt:v},v}execution(e,t){const i=this.prepared,n=i?.envelope.config_manifest,r=i?.execution;if(!(i&&"execution"===i.envelope.activation.kind&&n&&r&&isDeepStrictEqual(r.binding,t)&&containsApplied(this.config.current(),n.openclaw_config)))throw new Error("central execution does not match actual applied native configuration/Persona/binding");if(this.assertSelection(e,i.envelope),!isDeepStrictEqual(e,r.params))throw new Error("central execution differs from the prepared original request");return{sessionKey:r.sessionKey,localAgentId:n.local_agent_id,systemPrompt:n.persona?.content??""}}assertSelection(e,t){const i=e.centralChat,n=t.config_manifest.persona;if(!object(i)||!this.credentialReceipt||!isDeepStrictEqual(i.config_pin,this.credentialReceipt.config)||!isDeepStrictEqual(i.persona_ref,n?{persona_id:n.persona_id,revision:n.revision}:null)||Object.hasOwn(i,"effective_config")||Object.hasOwn(i,"persona"))throw new Error("central selection differs from the actual prepared native configuration/Persona source")}promptContext(e){if(this.persona&&object(e)&&e.agentId===this.persona.localAgentId)return{appendSystemContext:this.persona.content}}drain(e){return this.serialize(()=>this.quiesce(e))}async quiesce(e){if(!(this.prepared&&isDeepStrictEqual(e.activation,this.prepared.envelope.activation)&&isDeepStrictEqual(e.allocation,this.prepared.envelope.allocation)&&nonempty(e.command_id)))throw new Error("native drain does not match the actual prepared activation");const t=await centralNativeRuntime().drain();if(1!==t.sourceWatermarks.length)throw new Error("Runtime drain contract requires one actual central session watermark; configuration-only quiescence is not representable");const i=t.sourceWatermarks[0].watermark,n=ref({command_id:e.command_id,prepared:this.prepared.receipt.receipt_id,allocation:e.allocation,sources:t.sourceWatermarks});return{receipt_id:ref({quiesce:n,watermark:i}),central_committed_watermark:i,pending_writes:0,all_writers_quiesced:!0,quiesce_ref:n}}}let controller;async function body(e){const t=[];let i=0;for await(const n of e){const e=Buffer.isBuffer(n)?n:Buffer.from(n);if(i+=e.length,i>4194304)throw new Error("native activation payload exceeds 4 MiB");t.push(e)}try{return JSON.parse(Buffer.concat(t).toString("utf8"))}catch{throw new Error("native control request is not valid JSON")}}export function registerSandboxNativeActivation(e,t,i,n){const r=process.env.BEEOS_SANDBOX_ACTIVATION_FILE;if(!r)return;const a=e.runtime?.config;if(!a?.current||!a.mutateConfigFile)throw new Error("pinned OpenClaw native config APIs are required for Sandbox activation");controller??=new SandboxNativeActivation(a,t,r,i,n,e.logger);for(const t of["credentials","target","prepare","drain"])e.registerHttpRoute({path:`/beeos/sandbox-v1/${t}`,auth:"plugin",async handler(e,i){const n=e,r=i,a=(e,t)=>{r.writeHead(e,{"content-type":"application/json","cache-control":"no-store"}),r.end(JSON.stringify(t))};if("POST"!==n.method)return void a(405,{error:{code:"method_not_allowed"}});const o=n.socket.remoteAddress;if(["127.0.0.1","::1","::ffff:127.0.0.1"].includes(o??""))try{const e=process.env.BEEOS_SANDBOX_NATIVE_TOKEN_FILE;if(!e)throw new Error("native control token file is unavailable");const i=(await readFile(e,"utf8")).trim(),r=Buffer.from(`Bearer ${i}`),o=Buffer.from(n.headers.authorization??"");if(!i||o.length!==r.length||!timingSafeEqual(o,r))return void a(401,{error:{code:"native_control_unauthorized"}});const s=await body(n);if(!object(s))throw new Error("native control request must be an object");a(200,"credentials"===t?await controller.credentials(s):"target"===t?await controller.target(s):"prepare"===t?await controller.prepare(s):await controller.drain(s))}catch(e){a(503,{error:{code:"native_preparation_unavailable",message:e instanceof Error?e.message:String(e)}})}else a(403,{error:{code:"native_loopback_required"}})}})}export function preparedSandboxNativeExecution(e,t){if(!controller)throw new Error("actual native Sandbox activation is unavailable");return controller.execution(e,t)}
1
+ import{createHash,timingSafeEqual}from"node:crypto";import{readFile}from"node:fs/promises";import{isDeepStrictEqual}from"node:util";import{centralNativeRuntime}from"./central-native-runtime.js";import{resolveSyncAgentName}from"../agent-sync.js";import{injectOpenClawCredentials}from"./sandbox-native-credentials.js";function unboundActivation(e){const{execution_binding_version:t,...i}=e;return{...i,request_hash:""}}let executionResolver;export function installSandboxNativeExecutionResolver(e){if(executionResolver)throw new Error("native original execution authority is already installed");executionResolver=e}const TARGET_LOOKUP_INTERVAL_MS=250,TARGET_LOOKUP_STARTUP_TIMEOUT_MS=6e4,TARGET_LOOKUP_RUNTIME_TIMEOUT_MS=1e4;export function createSandboxNativeTargetLookup(e,t,i={}){const n=i.intervalMs??250,r={startup:i.startupTimeoutMs??6e4,runtime:i.runtimeTimeoutMs??1e4},a=i.now??Date.now,o=i.sleep??(e=>new Promise(t=>setTimeout(t,e)));let s=!1;return async({localAgentId:c,activation:l})=>{const d=s?"runtime":"startup",u=a();let p=0,h=[],f="";for(;;){p+=1;const _=e(),g=_?.authorityLease,v=t(),m=[];if(_||m.push("authority_missing"),_&&!g?.runtimeLeaseCredential&&m.push("lease_credential_missing"),g&&Date.parse(g.leaseExpiresAt)<=a()&&m.push("lease_expired"),g&&g.instanceId!==l.sandbox_id&&m.push("instance_mismatch"),v?.isConnected||m.push("gateway_disconnected"),_&&g&&v&&0===m.length){const t=await v.request("agents.list",{}),i=t.agents?.filter(e=>e.id===c)??[];if(1!==i.length)throw new Error("actual native target catalog entry is missing or ambiguous");if(resolveSyncAgentName(i[0])!==c)throw new Error("actual native catalog key differs from the current identity projection key");const n=await _.identities.resolveOrCreate(c),r=_.authorityLease;if(e()!==_||!r||Date.parse(r.leaseExpiresAt)<=a()||r.instanceId!==g.instanceId||r.leaseId!==g.leaseId||r.runtimeEpoch!==g.runtimeEpoch||r.handlerIdentity!==g.handlerIdentity)throw new Error("native target projection authority changed during observation");return s=!0,{runtimeAgentUid:n,runtimeLocalKey:c,runtimeEpoch:r.runtimeEpoch,leaseIdentity:JSON.stringify({instanceId:r.instanceId,leaseId:r.leaseId,runtimeEpoch:r.runtimeEpoch,handlerIdentity:r.handlerIdentity})}}h=m;const w=a()-u,y=m.join(",");if(y!==f&&(f=y,i.logger?.warn?.(`[beeos-claw] native target lookup pending: phase=${d} reason=${m[m.length-1]} unmet=${y} attempt=${p} elapsed_ms=${w} sandbox_id=${l.sandbox_id} instance_id=${g?.instanceId??"none"} lease_expires_at=${g?.leaseExpiresAt??"none"} lease_credential=${g?.runtimeLeaseCredential?"present":"missing"} gateway_connected=${!0===v?.isConnected}`)),w>=r[d])throw new Error(`current native target projection authority/catalog transport is unavailable: native target lookup timed out after ${r[d]}ms (phase=${d}, last_reason=${h[h.length-1]}, unmet=${h.join(",")}, attempts=${p}, sandbox_id=${l.sandbox_id})`);await o(Math.min(n,r[d]-w))}}}const object=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),sha256=e=>createHash("sha256").update(e).digest("hex"),ref=e=>`native:${sha256(JSON.stringify(e))}`,nonempty=e=>"string"==typeof e&&e.length>0,secretRef=e=>object(e)&&3===Object.keys(e).length&&("env"===e.source||"file"===e.source||"exec"===e.source)&&nonempty(e.provider)&&nonempty(e.id);export function containsApplied(e,t){return secretRef(t)?isDeepStrictEqual(e,t)||nonempty(e):Array.isArray(t)?Array.isArray(e)&&e.length===t.length&&t.every((t,i)=>containsApplied(e[i],t)):object(t)?object(e)&&Object.entries(t).every(([t,i])=>containsApplied(e[t],i)):isDeepStrictEqual(e,t)}export function sessionConfigObservation(e){const{activation:t,allocation:i,native:n,execution:r,receipt:a}=e,o=n.config_components;if(!(object(o)&&object(r.loadAuthority)&&Number.isSafeInteger(i.epoch)&&nonempty(t.resolved_request_hash)&&nonempty(t.central_read_watermark)))throw new Error("actual SessionConfigReceipt inputs (components/authority/allocation/selection) are unavailable");const s=structuredClone(r.loadAuthority),c=i.id,l=r.sessionKey,d={session_load_receipt:e.sessionLoadReceipt,prepared:a.receipt_id},u=ref({config:a.receipt_id,session:l,authority:s}),p={contractVersion:"1",revision:t.config_revision,manifestRef:{id:t.config_manifest.manifest_id,digest:t.config_sha256},appliedAt:a.prepared_at,sessionId:t.session_id,applyAt:"session_start",components:structuredClone(o),binding:{bindingId:t.binding_id,agentId:t.agent_id,harnessId:t.harness,sandboxId:t.sandbox_id,allocationId:i.id,allocationEpoch:i.epoch},applicationState:"applied",authority:s,hostInstanceId:c,nativeSessionId:l,receiptId:u,mutationScope:"session_private"};return{resolvedRequestHash:t.resolved_request_hash,readWatermark:t.central_read_watermark,admission:{attemptId:r.binding.attemptId,hostInstanceId:c,executionBindingVersion:t.execution_binding_version,nativeSessionId:l,nativeIncarnation:`${process.pid}@${i.boot_id}`,requestHash:t.request_hash},sessionConfigReceipt:{receiptId:u,commandId:t.command_id,authority:s,hostInstanceId:c,nativeSessionId:l,configuration:p,evidenceRef:{id:e.sessionLoadReceipt,digest:sha256(JSON.stringify(d))},preparedConfigReceiptId:a.receipt_id},loadedFacts:{loaded_model_id:null,actual_provider_id:null,actual_model_id:null,endpoint_ref:null,api_mode:null,reasoning:null,fallback_used:null,skills_digest:null,tool_schema_digest:null,credential_activation_revision:a.credential_activation_revision,components:[],memory_observation:"not_read",memory_read_watermark:null}}}export class SandboxNativeActivation{config;activeWriters;activationFile;targetLookup;reloadSecrets;logger;prepared;materialized;boundNativeRequestHash;targetAuthority;persona;credentialReceipt;reloadedCredentialsReceipt;control=Promise.resolve();serialize(e){const t=this.control.then(e,e);return this.control=t.catch(()=>{}),t}constructor(e,t,i,n,r,a){this.config=e,this.activeWriters=t,this.activationFile=i,this.targetLookup=n,this.reloadSecrets=r,this.logger=a}reloadSecretsAfterInjection(e){this.reloadSecrets&&this.reloadedCredentialsReceipt!==e&&(this.reloadedCredentialsReceipt=e,Promise.resolve().then(()=>this.reloadSecrets()).catch(t=>{this.reloadedCredentialsReceipt===e&&(this.reloadedCredentialsReceipt=void 0),this.logger?.warn?.(`[beeos-claw] secrets reload after credential delivery failed: ${t instanceof Error?t.message:String(t)}`)}))}prepare(e){return this.serialize(()=>this.apply(e))}target(e){return this.serialize(()=>this.apply(e,!0))}async assertEnvelope(e,t=!1){const i=JSON.parse(await readFile(this.activationFile,"utf8")),{activation:n,allocation:r,config_manifest:a}=e,o=!t&&"execution"===n.kind&&"execution"===i.activation?.kind&&""===i.activation.request_hash&&nonempty(n.request_hash)&&isDeepStrictEqual(unboundActivation(i.activation),unboundActivation(n));if(!isDeepStrictEqual(i.activation,n)&&!o||!isDeepStrictEqual(i.allocation,r)||!isDeepStrictEqual(i.config_manifest,a))throw new Error("native preparation does not match the current immutable activation");if(!nonempty(n.preparation_id)||!nonempty(r.id)||!nonempty(r.boot_id)||!Number.isFinite(Date.parse(n.deadline_at))||Date.parse(n.deadline_at)<=Date.now())throw new Error("native preparation authority/deadline is unavailable");if(!isDeepStrictEqual(JSON.parse(await readFile(e.config_manifest_path,"utf8")),a))throw new Error("native configuration bytes differ from the verified manifest");if("credential_activation"in a)throw new Error("private credential inputs must use transient authenticated delivery");if("central_chat"in a||"centralChat"in a)throw new Error("immutable native configuration must not contain per-execution chat authority")}credentials(e){return this.serialize(async()=>{if(await this.assertEnvelope(e),0!==this.activeWriters())throw new Error("native writers must drain before credential injection");if(this.materialized&&!this.credentialReceipt)throw new Error("credentials must be injected before native provider construction");const t=injectOpenClawCredentials({delivery:e.credential_delivery,activation:e.activation,allocation:e.allocation,previous:this.credentialReceipt,mcpCredentialSlots:e.config_manifest.mcp_credential_slots});return this.credentialReceipt=t,this.reloadSecretsAfterInjection(t.receipt_id),structuredClone(t)})}async apply(e,t=!1){await this.assertEnvelope(e,t);const{activation:i,allocation:n,config_manifest:r}=e;if(!this.credentialReceipt)throw new Error("actual native credential injection receipt is required, including empty credentials");if("execution"===i.kind){if(!nonempty(i.public_request_hash))throw new Error("original public request hash is required");if(t&&(""!==i.request_hash||void 0!==this.boundNativeRequestHash))throw new Error("target observation requires the original unbound native request hash");const e=i.execution_binding_version;if(t?void 0!==e&&0!==e:!(Number.isSafeInteger(e)&&e>=1))throw new Error("State execution binding version must be unbound at target and positive at Session load");if(!t&&(!nonempty(i.request_hash)||void 0!==this.boundNativeRequestHash&&this.boundNativeRequestHash!==i.request_hash))throw new Error("native canonical request hash is missing or changed")}const{execution_grant:a,credential_delivery:o,...s}=e,c={...s,activation:unboundActivation(i)};if(this.materialized&&!isDeepStrictEqual(this.materialized,c))throw new Error("a different native materialization requires a drained process restart");let l;if("execution"===i.kind&&!t){if(!nonempty(e.execution_grant)||!executionResolver)throw new Error("authenticated original canonical execution request producer is unavailable");if(l=await executionResolver(e),!this.targetAuthority||!this.targetLookup)throw new Error("the original work has no observed native target");const t=await this.targetLookup({localAgentId:r.local_agent_id,activation:i,allocation:n});if(!isDeepStrictEqual(t,this.targetAuthority))throw new Error("native target/current runtime lease changed before session load");if(l.nativeRequestHash!==i.request_hash||l.binding.sessionId!==i.session_id||l.binding.responseId!==i.response_id||l.binding.operationId!==i.operation_id||l.runtimeAgentUid!==this.targetAuthority.runtimeAgentUid||!l.sessionKey.startsWith(`agent:${r.local_agent_id}:`))throw new Error("original execution request differs from the current native activation");this.assertSelection(l.params,e)}if(!t&&this.prepared&&isDeepStrictEqual(this.prepared.envelope,s)){if(!isDeepStrictEqual(this.prepared.execution,l))throw new Error("original execution binding changed");return l&&await centralNativeRuntime().prepareReadOnly(l.sessionKey,l.binding),structuredClone(this.prepared.receipt)}if(0!==this.activeWriters())throw new Error("native writers must drain before applying configuration");if(!["configuration","credential_restart","execution"].includes(i.kind))throw new Error("unsupported native activation kind");if(1!==r.schema_version||!nonempty(r.local_agent_id)||!object(r.openclaw_config))throw new Error("resolved OpenClaw native configuration v1 is required");const d=r.mcp_credential_slots;if(void 0!==d&&(!Array.isArray(d)||d.some(e=>"string"!=typeof e||!/^[a-z][a-z0-9_]{0,63}$/.test(e)||"openai_api_key"===e)||new Set(d).size!==d.length))throw new Error("resolved MCP credential slots are invalid");const u=new Set(["agents","models","tools","skills","mcp"]);if(Object.keys(r.openclaw_config).some(e=>!u.has(e)))throw new Error("native config may only apply agent/model/tool/Skill/MCP settings");const p=r.openclaw_config.agents;if(!object(p)||!object(p.entries)||!object(p.entries[r.local_agent_id]))throw new Error("local_agent_id is not present in the resolved native agent catalog");if(this.prepared&&!isDeepStrictEqual(this.prepared.envelope,s))throw new Error("a different native activation requires a drained process restart");if(r.persona&&(!nonempty(r.persona.persona_id)||!nonempty(r.persona.revision)||!nonempty(r.persona.source_receipt_ref)||sha256(r.persona.content)!==r.persona.sha256))throw new Error("resolved Persona source/revision/content digest is invalid");if("execution"!==i.kind&&(i.session_id||i.response_id||i.execution_binding_version))throw new Error("non-execution preparation must not manufacture a Session or Response");if(t&&"execution"!==i.kind)throw new Error("target observation requires the original execution preparation");this.materialized||await this.config.mutateConfigFile({afterWrite:{mode:"auto"},mutate:e=>{for(const[t,i]of Object.entries(r.openclaw_config))e[t]=structuredClone(i)}});const h=this.config.current();if(!containsApplied(h,r.openclaw_config))throw new Error("native config has not been applied by OpenClaw");const f=h.agents;if(!object(f)||!object(f.entries)||!object(f.entries[r.local_agent_id]))throw new Error("local_agent_id is not present in the actual resolved native agent catalog");if(this.persona=r.persona?{localAgentId:r.local_agent_id,content:r.persona.content}:void 0,this.materialized=structuredClone(c),t){if(!this.targetLookup)throw new Error("actual native target identity producer is unavailable");const e=await this.targetLookup({localAgentId:r.local_agent_id,activation:i,allocation:n});if(!nonempty(e.runtimeAgentUid)||e.runtimeLocalKey!==r.local_agent_id||!/^[1-9][0-9]*$/.test(e.runtimeEpoch)||!nonempty(e.leaseIdentity))throw new Error("actual native catalog/identity projection does not match the applied target");return this.targetAuthority=structuredClone(e),{runtime_agent_uid:e.runtimeAgentUid,runtime_local_key:e.runtimeLocalKey,harness:"openclaw",config_digest:i.config_sha256,runtime_epoch:e.runtimeEpoch}}let _="";if("execution"===i.kind){if(!l)throw new Error("original central native execution authority is unavailable");this.boundNativeRequestHash=l.nativeRequestHash,await centralNativeRuntime().prepareReadOnly(l.sessionKey,l.binding),_=ref({session_key:l.sessionKey,binding:l.binding,source:centralNativeRuntime().source(l.sessionKey)})}const g=(new Date).toISOString(),v={preparation_id:i.preparation_id,kind:i.kind,binding_id:i.binding_id,config_revision:i.config_revision,config_sha256:i.config_sha256,target_intent_digest:i.target_intent_digest,authority_ref:i.authority_ref,config_manifest:i.config_manifest,credential_set_id:i.credential_set_id,credential_set_version:i.credential_set_version,credential_activation_revision:this.credentialReceipt.config.revision,receipt_scope:"configuration"===i.kind?"current_config":"activation",credential_activation_receipt_ref:this.credentialReceipt.receipt_id,host_instance_id:n.id,runtime_lineage_ref:n.boot_id,session_load_receipt_ref:_,prepared_at:g,..."execution"===i.kind?{execution_binding_version:i.execution_binding_version}:{},receipt_id:ref({activation:i,allocation:n,config:r.openclaw_config,persona:r.persona?.sha256??null,credential_receipt:this.credentialReceipt.receipt_id,sessionLoadReceipt:_})};return l&&centralNativeRuntime().bindExecutionObservation(l.binding,sessionConfigObservation({activation:i,allocation:n,native:r,execution:l,receipt:v,sessionLoadReceipt:_})),this.prepared={envelope:structuredClone(s),execution:l&&structuredClone(l),receipt:v},v}execution(e,t){const i=this.prepared,n=i?.envelope.config_manifest,r=i?.execution;if(!(i&&"execution"===i.envelope.activation.kind&&n&&r&&isDeepStrictEqual(r.binding,t)&&containsApplied(this.config.current(),n.openclaw_config)))throw new Error("central execution does not match actual applied native configuration/Persona/binding");if(this.assertSelection(e,i.envelope),!isDeepStrictEqual(e,r.params))throw new Error("central execution differs from the prepared original request");return{sessionKey:r.sessionKey,localAgentId:n.local_agent_id,systemPrompt:n.persona?.content??""}}assertSelection(e,t){const i=e.centralChat,n=t.config_manifest.persona;if(!object(i)||!this.credentialReceipt||!isDeepStrictEqual(i.config_pin,this.credentialReceipt.config)||!isDeepStrictEqual(i.persona_ref,n?{persona_id:n.persona_id,revision:n.revision}:null)||Object.hasOwn(i,"effective_config")||Object.hasOwn(i,"persona"))throw new Error("central selection differs from the actual prepared native configuration/Persona source")}promptContext(e){if(this.persona&&object(e)&&e.agentId===this.persona.localAgentId)return{appendSystemContext:this.persona.content}}drain(e){return this.serialize(()=>this.quiesce(e))}async quiesce(e){if(!(this.prepared&&isDeepStrictEqual(e.activation,this.prepared.envelope.activation)&&isDeepStrictEqual(e.allocation,this.prepared.envelope.allocation)&&nonempty(e.command_id)))throw new Error("native drain does not match the actual prepared activation");const t=await centralNativeRuntime().drain();if(1!==t.sourceWatermarks.length)throw new Error("Runtime drain contract requires one actual central session watermark; configuration-only quiescence is not representable");const i=t.sourceWatermarks[0].watermark,n=ref({command_id:e.command_id,prepared:this.prepared.receipt.receipt_id,allocation:e.allocation,sources:t.sourceWatermarks});return{receipt_id:ref({quiesce:n,watermark:i}),central_committed_watermark:i,pending_writes:0,all_writers_quiesced:!0,quiesce_ref:n}}}let controller;async function body(e){const t=[];let i=0;for await(const n of e){const e=Buffer.isBuffer(n)?n:Buffer.from(n);if(i+=e.length,i>4194304)throw new Error("native activation payload exceeds 4 MiB");t.push(e)}try{return JSON.parse(Buffer.concat(t).toString("utf8"))}catch{throw new Error("native control request is not valid JSON")}}export function registerSandboxNativeActivation(e,t,i,n){const r=process.env.BEEOS_SANDBOX_ACTIVATION_FILE;if(!r)return;const a=e.runtime?.config;if(!a?.current||!a.mutateConfigFile)throw new Error("pinned OpenClaw native config APIs are required for Sandbox activation");controller??=new SandboxNativeActivation(a,t,r,i,n,e.logger);for(const t of["credentials","target","prepare","drain"])e.registerHttpRoute({path:`/beeos/sandbox-v1/${t}`,auth:"plugin",async handler(e,i){const n=e,r=i,a=(e,t)=>{r.writeHead(e,{"content-type":"application/json","cache-control":"no-store"}),r.end(JSON.stringify(t))};if("POST"!==n.method)return void a(405,{error:{code:"method_not_allowed"}});const o=n.socket.remoteAddress;if(["127.0.0.1","::1","::ffff:127.0.0.1"].includes(o??""))try{const e=process.env.BEEOS_SANDBOX_NATIVE_TOKEN_FILE;if(!e)throw new Error("native control token file is unavailable");const i=(await readFile(e,"utf8")).trim(),r=Buffer.from(`Bearer ${i}`),o=Buffer.from(n.headers.authorization??"");if(!i||o.length!==r.length||!timingSafeEqual(o,r))return void a(401,{error:{code:"native_control_unauthorized"}});const s=await body(n);if(!object(s))throw new Error("native control request must be an object");a(200,"credentials"===t?await controller.credentials(s):"target"===t?await controller.target(s):"prepare"===t?await controller.prepare(s):await controller.drain(s))}catch(e){a(503,{error:{code:"native_preparation_unavailable",message:e instanceof Error?e.message:String(e)}})}else a(403,{error:{code:"native_loopback_required"}})}})}export function preparedSandboxNativeExecution(e,t){if(!controller)throw new Error("actual native Sandbox activation is unavailable");return controller.execution(e,t)}
@@ -1 +1 @@
1
- import{prepareNativeOutputTool,nativeHtmlDeliveryForRun}from"../runtime/native-output-file-attempt.js";import{RENDER_UI_TOOL_NAME}from"../canvas/tools.js";import{BEEOS_FETCH_FILE_TOOL_NAME}from"../files/fetch-tool.js";import{BEEOS_UPLOAD_TOOL_NAME}from"./tool.js";export function needsNativeOutputCapability(t,o){return t===BEEOS_UPLOAD_TOOL_NAME||t===BEEOS_FETCH_FILE_TOOL_NAME||t===RENDER_UI_TOOL_NAME&&Object.prototype.hasOwnProperty.call(o,"html")}export function nativeOutputToolCallGate(t,o){if(needsNativeOutputCapability(t.toolName,t.params)){if(t.runId&&o.runId&&t.runId!==o.runId||t.toolCallId&&o.toolCallId&&t.toolCallId!==o.toolCallId)return{block:!0,blockReason:"native output file Host correlation conflict"};try{const e=t.runId??o.runId;if(nativeHtmlDeliveryForRun(e)?.observeAttempt(t.toolName,t.params),t.toolName===RENDER_UI_TOOL_NAME&&nativeHtmlDeliveryForRun(e)?.publishedFileId)return{block:!0,blockReason:"The HTML file for this reply is already published. Use that result; do not generate or upload another copy."};prepareNativeOutputTool(e,t.toolCallId??o.toolCallId)}catch{return{block:!0,blockReason:"native output file trusted capability unavailable"}}}}
1
+ import{prepareNativeOutputTool,nativeHtmlDeliveryForRun,nativeOutputBindingDiagnostic}from"../runtime/native-output-file-attempt.js";import{RENDER_UI_TOOL_NAME}from"../canvas/tools.js";import{BEEOS_FETCH_FILE_TOOL_NAME}from"../files/fetch-tool.js";import{BEEOS_UPLOAD_TOOL_NAME}from"./tool.js";export function needsNativeOutputCapability(t,o){return t===BEEOS_UPLOAD_TOOL_NAME||t===BEEOS_FETCH_FILE_TOOL_NAME||t===RENDER_UI_TOOL_NAME&&Object.prototype.hasOwnProperty.call(o,"html")}export function nativeOutputToolCallGate(t,o,e){if(!needsNativeOutputCapability(t.toolName,t.params))return;const l=t.runId??o.runId,i=t.toolCallId??o.toolCallId,a=o.sessionKey;if(t.runId&&o.runId&&t.runId!==o.runId||t.toolCallId&&o.toolCallId&&t.toolCallId!==o.toolCallId)return e?.warn?.("[beeos-claw] native output capability blocked "+JSON.stringify(nativeOutputBindingDiagnostic({runId:l,toolCallId:i,sessionKey:a,error:new Error("native output file Host correlation conflict")}))),{block:!0,blockReason:"native output file Host correlation conflict"};try{if(nativeHtmlDeliveryForRun(l)?.observeAttempt(t.toolName,t.params),t.toolName===RENDER_UI_TOOL_NAME&&nativeHtmlDeliveryForRun(l)?.publishedFileId)return{block:!0,blockReason:"The HTML file for this reply is already published. Use that result; do not generate or upload another copy."};prepareNativeOutputTool(l,i,a)}catch(t){return e?.warn?.("[beeos-claw] native output capability blocked "+JSON.stringify(nativeOutputBindingDiagnostic({runId:l,toolCallId:i,sessionKey:a,error:t}))),{block:!0,blockReason:"native output file trusted capability unavailable"}}}
@@ -1 +1 @@
1
- import{constants}from"node:fs";import{access,stat}from"node:fs/promises";import{uploadLocalFile,NativeOutputFilesError}from"./upload-file.js";import{isBeeosFileUri}from"../files/beeos-file-uri.js";export const BEEOS_UPLOAD_TOOL_NAME="beeos_upload_file";export const BEEOS_UPLOAD_TOOL_DESCRIPTION="Upload 1-5 local files from this machine to the user via the BeeOS platform. This is the only way to deliver a file to the user: whenever you produce or modify a file the user asked for, call this tool with its path. Writing the file to disk or printing it through a shell command does not deliver it. Accepts only local filesystem paths; never pass beeos-file:// URIs because they are already BeeOS platform resources. If the call succeeds, the files are already delivered to the user — do not use any other tool to send them again. Upload modified deliverables again even if the same path was uploaded earlier; unchanged contents may reuse an existing platform file. Any file type is accepted: text, images, documents, PDFs, archives, binaries.";export const BEEOS_UPLOAD_TOOL_SCHEMA={title:"BeeOS file upload",type:"object",description:BEEOS_UPLOAD_TOOL_DESCRIPTION,additionalProperties:!1,required:["paths"],properties:{paths:{type:"array",minItems:1,maxItems:5,description:"Local filesystem paths (1-5). Absolute or workspace-relative. Do not pass beeos-file:// URIs.",items:{type:"string",minLength:1,description:"Single local filesystem path, not a beeos-file:// URI."}}}};const MAX_PATHS=5;export const REQUEST_TIMEOUT_MS=12e4;const MAX_CONCURRENCY=3,BEEOS_FILE_URI_UPLOAD_ERROR="beeos-file:// is already a BeeOS platform file URI, not a local path. Do not upload it; display it directly.";async function runWithConcurrency(e,t){const r=new Array(e.length);let a=0;async function o(){for(;a<e.length;){const t=a++;r[t]=await e[t]()}}const i=[];for(let r=0;r<Math.min(t,e.length);r++)i.push(o());return await Promise.all(i),r}async function validateFiles(e){return Promise.all(e.map(async e=>{try{await access(e,constants.R_OK);return(await stat(e)).isFile()?{path:e,ok:!0}:{path:e,ok:!1,error:"not a regular file"}}catch(t){const r=t.code;let a;return a="ENOENT"===r?"file not found":"ENOTDIR"===r?"path component is not a directory":"EACCES"===r?"permission denied":t instanceof Error?t.message:String(t),{path:e,ok:!1,error:a}}}))}export async function executeUpload(e,t,r,a,o){const i=parseParams(e);if(!i.ok)return errorResult(i.error);if(!t&&!a)return errorResult("Agent Gateway client unavailable — file upload requires agentGatewayUrl and a key pair");const s=i.paths,n=(await validateFiles(s)).find(e=>!e.ok);if(n)return errorResult(`${n.path}: ${n.error}`);const l=[],c=s.map((e,i)=>async()=>{try{if(a){const t=await a(e,i);return{fileId:t.fileId,downloadUrl:"",fileName:t.name,mimeType:t.mimeType,size:t.size}}return await uploadSingleFile(e,t,r)}catch(t){if(r?.aborted)throw t;const{category:s,detail:n}=classifyUploadFailure(t,Boolean(a));return o?.warn?.(`[beeos_upload_file] upload failed index=${i} native=${Boolean(a)} category=${s} ${n}`),l.push(a?t instanceof NativeOutputFilesError?t.message:"native output Files transport or local read failed":`${e}: ${t instanceof Error?t.message:String(t)}`),null}}),p=(await runWithConcurrency(c,3)).filter(e=>null!==e);if(0===p.length)return errorResult(`All uploads failed: ${l.join("; ")}`);const u=p.map(e=>({uri:`beeos-file://${e.fileId}`,name:e.fileName,mimeType:e.mimeType,fileId:e.fileId})),f=p.length===s.length?`Uploaded ${p.length} file(s): ${u.map(e=>e.name).join(", ")}`:`Uploaded ${p.length}/${s.length} file(s): ${u.map(e=>e.name).join(", ")}. Failed: ${l.join("; ")}`,m={ok:!0,files:u};return{...m,content:[{type:"text",text:f},...u.map(e=>({type:"resource_link",uri:e.uri,name:e.name,mimeType:e.mimeType}))],output:m,result:m,details:m,isError:!1}}async function uploadSingleFile(e,t,r){const a=await uploadLocalFile(e,t,{signal:r,timeoutMs:12e4});return{fileId:a.fileId,downloadUrl:"",fileName:a.name,mimeType:a.mimeType,size:a.size}}function parseParams(e){if(!e||"object"!=typeof e)return{ok:!1,error:"params must be an object"};const t=e;if(Object.keys(t).filter(e=>"paths"!==e).length>0)return{ok:!1,error:"only paths is allowed"};if(!Array.isArray(t.paths))return{ok:!1,error:"paths must be an array"};if(t.paths.length<1)return{ok:!1,error:"paths must contain at least 1 item"};if(t.paths.length>5)return{ok:!1,error:"paths must contain no more than 5 items"};const r=[];for(let e=0;e<t.paths.length;e++){const a=t.paths[e];if("string"!=typeof a||""===a.trim())return{ok:!1,error:`paths[${e}] must be a non-empty string`};const o=a.trim();if(isBeeosFileUri(o))return{ok:!1,error:BEEOS_FILE_URI_UPLOAD_ERROR};r.push(o)}return{ok:!0,paths:r}}function classifyUploadFailure(e,t){const r=e instanceof Error?e.message:String(e),a=e instanceof Error&&e.cause instanceof Error?` cause=${e.cause.message}`:"";if(e instanceof NativeOutputFilesError)return{category:e.category,detail:`${e.detail??""} message=${r}`.trim()};if(e instanceof DOMException&&("AbortError"===e.name||"TimeoutError"===e.name))return{category:"aborted",detail:`name=${e.name} message=${r}`};if(e instanceof TypeError)return{category:"transport_rejected",detail:`message=${r}${a}`};const o=e?.code;return"string"==typeof o?{category:"local_read_failed",detail:`code=${o} message=${r}`}:{category:t?"attempt_or_lease_fenced":"unclassified",detail:`message=${r}${a}`}}function errorResult(e){const t={ok:!1,error:e};return{...t,content:[{type:"text",text:e}],output:t,result:t,details:t,isError:!0}}
1
+ import{constants}from"node:fs";import{access,stat}from"node:fs/promises";import{uploadLocalFile,NativeOutputFilesError,nativeOutputPathWithinWorkspace}from"./upload-file.js";import{isBeeosFileUri}from"../files/beeos-file-uri.js";export const BEEOS_UPLOAD_TOOL_NAME="beeos_upload_file";export const BEEOS_UPLOAD_TOOL_DESCRIPTION="Upload 1-5 local files from this machine to the user via the BeeOS platform. This is the only way to deliver a file to the user: whenever you produce or modify a file the user asked for, call this tool with its path. Writing the file to disk or printing it through a shell command does not deliver it. Accepts only local filesystem paths; never pass beeos-file:// URIs because they are already BeeOS platform resources. If the call succeeds, the files are already delivered to the user — do not use any other tool to send them again. Upload modified deliverables again even if the same path was uploaded earlier; unchanged contents may reuse an existing platform file. Any file type is accepted: text, images, documents, PDFs, archives, binaries.";export const BEEOS_UPLOAD_TOOL_SCHEMA={title:"BeeOS file upload",type:"object",description:BEEOS_UPLOAD_TOOL_DESCRIPTION,additionalProperties:!1,required:["paths"],properties:{paths:{type:"array",minItems:1,maxItems:5,description:"Local filesystem paths (1-5). Absolute or workspace-relative. Do not pass beeos-file:// URIs.",items:{type:"string",minLength:1,description:"Single local filesystem path, not a beeos-file:// URI."}}}};const MAX_PATHS=5;export const REQUEST_TIMEOUT_MS=12e4;const MAX_CONCURRENCY=3,BEEOS_FILE_URI_UPLOAD_ERROR="beeos-file:// is already a BeeOS platform file URI, not a local path. Do not upload it; display it directly.";async function runWithConcurrency(e,t){const r=new Array(e.length);let a=0;async function o(){for(;a<e.length;){const t=a++;r[t]=await e[t]()}}const i=[];for(let r=0;r<Math.min(t,e.length);r++)i.push(o());return await Promise.all(i),r}async function validateFiles(e){return Promise.all(e.map(async e=>{try{await access(e,constants.R_OK);return(await stat(e)).isFile()?{path:e,ok:!0}:{path:e,ok:!1,error:"not a regular file"}}catch(t){const r=t.code;let a;return a="ENOENT"===r?"file not found":"ENOTDIR"===r?"path component is not a directory":"EACCES"===r?"permission denied":t instanceof Error?t.message:String(t),{path:e,ok:!1,error:a}}}))}export async function executeUpload(e,t,r,a,o,i){const s=parseParams(e);if(!s.ok)return errorResult(s.error);if(!t&&!a)return errorResult("Agent Gateway client unavailable — file upload requires agentGatewayUrl and a key pair");let n=s.paths;if(a){const e=[];for(const t of n)try{e.push(await nativeOutputPathWithinWorkspace(t,i))}catch(e){return errorResult(`${t}: ${e instanceof Error?e.message:String(e)}`)}n=e}const l=(await validateFiles(n)).find(e=>!e.ok);if(l)return errorResult(`${l.path}: ${l.error}`);const c=[],p=n.map((e,i)=>async()=>{try{if(a){const t=await a(e,i);return{fileId:t.fileId,downloadUrl:"",fileName:t.name,mimeType:t.mimeType,size:t.size}}return await uploadSingleFile(e,t,r)}catch(t){if(r?.aborted)throw t;const{category:s,detail:n}=classifyUploadFailure(t,Boolean(a));return o?.warn?.(`[beeos_upload_file] upload failed index=${i} native=${Boolean(a)} category=${s} ${n}`),c.push(a?t instanceof NativeOutputFilesError?t.message:"native output Files transport or local read failed":`${e}: ${t instanceof Error?t.message:String(t)}`),null}}),u=(await runWithConcurrency(p,3)).filter(e=>null!==e);if(0===u.length)return errorResult(`All uploads failed: ${c.join("; ")}`);const f=u.map(e=>({uri:`beeos-file://${e.fileId}`,name:e.fileName,mimeType:e.mimeType,fileId:e.fileId})),m=u.length===n.length?`Uploaded ${u.length} file(s): ${f.map(e=>e.name).join(", ")}`:`Uploaded ${u.length}/${n.length} file(s): ${f.map(e=>e.name).join(", ")}. Failed: ${c.join("; ")}`,d={ok:!0,files:f};return{...d,content:[{type:"text",text:m},...f.map(e=>({type:"resource_link",uri:e.uri,name:e.name,mimeType:e.mimeType}))],output:d,result:d,details:d,isError:!1}}async function uploadSingleFile(e,t,r){const a=await uploadLocalFile(e,t,{signal:r,timeoutMs:12e4});return{fileId:a.fileId,downloadUrl:"",fileName:a.name,mimeType:a.mimeType,size:a.size}}function parseParams(e){if(!e||"object"!=typeof e)return{ok:!1,error:"params must be an object"};const t=e;if(Object.keys(t).filter(e=>"paths"!==e).length>0)return{ok:!1,error:"only paths is allowed"};if(!Array.isArray(t.paths))return{ok:!1,error:"paths must be an array"};if(t.paths.length<1)return{ok:!1,error:"paths must contain at least 1 item"};if(t.paths.length>5)return{ok:!1,error:"paths must contain no more than 5 items"};const r=[];for(let e=0;e<t.paths.length;e++){const a=t.paths[e];if("string"!=typeof a||""===a.trim())return{ok:!1,error:`paths[${e}] must be a non-empty string`};const o=a.trim();if(isBeeosFileUri(o))return{ok:!1,error:BEEOS_FILE_URI_UPLOAD_ERROR};r.push(o)}return{ok:!0,paths:r}}function classifyUploadFailure(e,t){const r=e instanceof Error?e.message:String(e),a=e instanceof Error&&e.cause instanceof Error?` cause=${e.cause.message}`:"";if(e instanceof NativeOutputFilesError)return{category:e.category,detail:`${e.detail??""} message=${r}`.trim()};if(e instanceof DOMException&&("AbortError"===e.name||"TimeoutError"===e.name))return{category:"aborted",detail:`name=${e.name} message=${r}`};if(e instanceof TypeError)return{category:"transport_rejected",detail:`message=${r}${a}`};const o=e?.code;return"string"==typeof o?{category:"local_read_failed",detail:`code=${o} message=${r}`}:{category:t?"attempt_or_lease_fenced":"unclassified",detail:`message=${r}${a}`}}function errorResult(e){const t={ok:!1,error:e};return{...t,content:[{type:"text",text:e}],output:t,result:t,details:t,isError:!0}}