beeos-claw 0.6.63-cloud.0 → 0.6.63-cloud.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/a2a/tools.js +1 -1
- package/dist/acp-gateway/beeos-file-resolver.js +1 -1
- package/dist/acp-gateway/bridge-core.js +1 -1
- package/dist/acp-gateway/gateway-events.js +1 -1
- package/dist/acp-server.js +1 -1
- package/dist/agent-sync.js +1 -1
- package/dist/automation/tools.js +1 -0
- package/dist/automation/turn-policy.js +1 -0
- package/dist/automation/wake.js +1 -0
- package/dist/canvas/relay-client.js +1 -1
- package/dist/canvas/ws-provider.js +1 -1
- package/dist/canvas-orchestrator.js +1 -1
- package/dist/chat-envelope.js +1 -0
- package/dist/connectors/managed-connector-tools.js +1 -0
- package/dist/files/fetch-tool.js +1 -1
- package/dist/files/list-tool.js +1 -1
- package/dist/im-inbound-handler.js +1 -1
- package/dist/im-runtime-dispatch.js +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp-connector-proxy.js +1 -1
- package/dist/media/arouter-config.js +1 -1
- package/dist/media/image-provider.js +1 -1
- package/dist/media/video-provider.js +1 -1
- package/dist/message-client-composition.js +1 -1
- package/dist/runtime/agent-projection-production.js +1 -1
- package/dist/runtime/callback-queue.js +1 -1
- package/dist/runtime/chat-handler-port.js +1 -0
- package/dist/runtime/conversation-title.js +1 -1
- package/dist/runtime/core-execution-attempt-context.js +1 -1
- package/dist/runtime/im-reply-sink.js +1 -1
- package/dist/runtime/message-service-conversation-clear-http-authority.js +1 -1
- package/dist/runtime/message-service-conversation-history-boundary.js +1 -1
- package/dist/runtime/message-service-conversation-run-boundary.js +1 -1
- package/dist/runtime/message-service-cron-delivery-http-authority.js +1 -1
- package/dist/runtime/message-service-runtime-authenticated-fetch.js +1 -1
- package/dist/runtime/message-service-runtime-claim-authority.js +1 -1
- package/dist/runtime/message-service-runtime-message-channel.js +1 -1
- package/dist/runtime/message-service-session-model-http-authority.js +1 -1
- package/dist/runtime/ms-runtime-message-channel-adapter.js +1 -1
- package/dist/runtime/ms-runtime-message-channel-consumer-factory.js +1 -1
- package/dist/runtime/ms-runtime-rpc-adapter.js +1 -1
- package/dist/runtime/native-cloud-chat-composition.js +1 -0
- package/dist/runtime/native-cloud-prompt-bridge.js +1 -0
- package/dist/runtime/native-input-files-http.js +1 -0
- package/dist/runtime/native-input-files.js +1 -0
- package/dist/runtime/native-output-file-attempt.js +1 -0
- package/dist/runtime/native-prompt-authority.js +1 -0
- package/dist/runtime/native-prompt-preflight.js +1 -0
- package/dist/runtime/native-session-new-bridge.js +1 -0
- package/dist/runtime/openclaw-session-model.js +1 -0
- package/dist/runtime/reply-router.js +1 -1
- package/dist/runtime/runtime-error-part.js +1 -0
- package/dist/runtime/runtime-local-parity-matrix.js +1 -1
- package/dist/runtime/runtime-message-channel-contract.js +1 -1
- package/dist/runtime/runtime-operation-resource-resolver.js +1 -1
- package/dist/runtime/runtime-parity-manifest-digest.js +1 -1
- package/dist/runtime/runtime-parity-manifest.js +1 -1
- package/dist/runtime/runtime-production-authority.js +1 -1
- package/dist/runtime/runtime-registration-identity-store.js +1 -1
- package/dist/runtime/runtime-service-contract-compatibility.js +1 -1
- package/dist/runtime/runtime-service-production-candidate.js +1 -1
- package/dist/runtime/runtime-session-control-service.js +1 -1
- package/dist/runtime/runtime-skills-service.js +1 -1
- package/dist/runtime/service-runtime-attempt-ports-resolver.js +1 -1
- package/dist/runtime/session-new-runtime-delivery-bridge.js +1 -1
- package/dist/runtime/write-runtime-failure.js +1 -1
- package/dist/terminal/runtime-terminal-outbound-registration.js +1 -1
- package/dist/terminal/terminal-lease-bound-bridge-client.js +1 -1
- package/dist/upload/desktop-screenshot-tool.js +1 -1
- package/dist/upload/finalize-hook.js +1 -1
- package/dist/upload/tool-artifact-enrichment.js +1 -1
- package/dist/upload/tool.js +1 -1
- package/dist/upload/upload-file.js +1 -1
- package/openclaw.plugin.json +20 -2
- package/package.json +5 -4
- package/runtime-service-wire-identity.v1.json +5 -5
- package/dist/agent-auth.js +0 -1
- package/dist/bridge-discovery.js +0 -1
- package/dist/runtime/agent-gateway-runtime-attempt-authorization.js +0 -1
- package/dist/runtime/message-service-runtime-invocation-authority.js +0 -1
- package/dist/runtime/runtime-jwks-verifier.js +0 -1
- package/dist/runtime/runtime-registration.js +0 -1
- package/dist/runtime/runtime-transport-failure-policy.js +0 -1
- package/dist/runtime/split-runtime-authorization-verifier.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID}from"node:crypto";import{verifyAndCreateServiceCoreExecutionAttempt}from"./core-execution-attempt-context.js";import{RuntimeCommandError}from"./runtime-command-dispatcher.js";import{RuntimeClaimAuthorityProtocolError}from"./message-service-runtime-claim-authority.js";import{sessionSetModelMappingMatches}from"./session-set-model-mapping.js";import{RuntimeTransportFailurePolicy}from"./runtime-transport-failure-policy.js";export class MsRuntimeRpcAdapter{dispatcher;authority;authorizationVerifier;attemptPorts;authorizationJournal;getLease;options;controller;running;constructor(e,t,r,a,n,o,i){this.dispatcher=e,this.authority=t,this.authorizationVerifier=r,this.attemptPorts=a,this.authorizationJournal=n,this.getLease=o,this.options=i}start(){if(this.running)return;this.controller=new AbortController;const e=this.loop(this.controller.signal).finally(()=>{this.running===e&&(this.running=void 0)});this.running=e}async stop(e){const t=this.running;if(this.controller?.abort(),!t)return;await waitForAbort(t,e)===aborted&&this.running===t&&(this.running=void 0)}journalLineage(){return this.options.getJournalLineage?.()??{journalStoreId:this.options.journalStoreId,journalGeneration:this.options.journalGeneration}}async loop(e){let t=randomUUID(),r="",a="";for(;!e.aborted;){const n=this.getLease();if(!n){await delay(this.options.pollDelayMs??1e3,e);continue}const o=this.journalLineage(),i=`${n.instanceId}\n${n.runtimeEpoch}\n${this.options.handlerIdentity}\n${o.journalStoreId}\n${o.journalGeneration}`;if(r&&r!==i&&(t=randomUUID()),r=i,a!==i)try{const t=await this.authorizationJournal.listRecoverable(n.runtimeEpoch);for(const r of t){if(e.aborted||this.getLease()?.leaseId!==n.leaseId)break;if(!await this.recoverExact({operationId:r.operationId,requestMessageId:r.requestMessageId,dispatchEpoch:r.runtimeEpoch},n,e))throw new Error("durable runtime invocation is still owned by another claim")}a=i}catch{await delay(this.options.pollDelayMs??1e3,e);continue}let s;try{const r=this.authority.claimNext({claimRequestId:t,instanceId:n.instanceId,handlerIdentity:this.options.handlerIdentity,runtimeEpoch:n.runtimeEpoch,journalStoreId:o.journalStoreId,journalGeneration:o.journalGeneration,runtimeLeaseCredential:n.runtimeLeaseCredential}),a=await waitForAbort(r,e);if(a===aborted)return;s=a}catch(t){if(e.aborted)return;if(t instanceof RuntimeClaimAuthorityProtocolError)return;await delay(this.options.pollDelayMs??1e3,e);continue}if(e.aborted)return;t=randomUUID(),"empty"!==s.status?"fenced"!==s.status?await this.handleClaimed(s,n,e,"start").catch(()=>{}):await delay(this.options.pollDelayMs??1e3,e):await delay(Math.max(s.retryAfterMs,this.options.pollDelayMs??0),e)}}async recoverExact(e,t,r){if(e.dispatchEpoch!==t.runtimeEpoch)throw new Error("recovery candidate runtime epoch mismatch");const a=this.journalLineage(),n=await this.authority.claimExact({operationId:e.operationId,requestMessageId:e.requestMessageId,handlerIdentity:this.options.handlerIdentity,dispatchEpoch:e.dispatchEpoch,runtimeEpoch:t.runtimeEpoch,journalStoreId:a.journalStoreId,journalGeneration:a.journalGeneration,runtimeLeaseCredential:t.runtimeLeaseCredential});return"terminal"===n.status?(await this.authorizationJournal.markTerminal(e.operationId).catch(()=>{}),!0):"claimed"===n.status&&(await this.handleClaimed(n,t,r,"recovery"),!0)}async handleClaimed(e,t,r,a="start"){const n={operationId:e.request.operationId,requestMessageId:e.request.messageId,dispatchEpoch:e.request.payload.command.context.dispatchEpoch},o=async()=>{await this.authorizationJournal.markTerminal(n.operationId).catch(()=>{})},i=async e=>{await this.authority.commitFailure(e),await o()},s=()=>{const r=this.getLease(),a=r?.leaseId===t.leaseId&&r.runtimeEpoch===t.runtimeEpoch?r.runtimeLeaseCredential:t.runtimeLeaseCredential;return{operationId:n.operationId,requestMessageId:n.requestMessageId,...e.fence,runtimeLeaseCredential:a}},c=async e=>{try{await i(e)}finally{await this.authority.releaseClaim({...s(),reason:"claim_rejected"}).catch(()=>{})}};if(e.cancelRequested)return await i({operationId:n.operationId,requestMessageId:n.requestMessageId,request:e.request,fence:e.fence,claimLeaseExpiresAt:e.leaseExpiresAt,runtimeLeaseCredential:t.runtimeLeaseCredential,attempt:prestartAttempt(e.request),outcome:"cancelled",code:"OPERATION_CANCELLED"}),void await this.authority.releaseClaim({...s(),reason:"cancelled"});let u;try{u=await this.authorizationJournal.prepare({operationId:n.operationId,requestMessageId:n.requestMessageId,method:e.request.payload.request.method,commandHash:e.request.payload.commandHash,runtimeEpoch:t.runtimeEpoch,journalStoreId:e.fence.journalStoreId,journalGeneration:e.fence.journalGeneration})}catch{return void await c({operationId:n.operationId,requestMessageId:n.requestMessageId,request:e.request,fence:e.fence,claimLeaseExpiresAt:e.leaseExpiresAt,runtimeLeaseCredential:t.runtimeLeaseCredential,attempt:prestartAttempt(e.request),outcome:"failed",code:"UNAUTHORIZED_TARGET"}).catch(()=>{})}const d=await this.authority.authorize({request:e.request,fence:e.fence,lease:t,journal:u});if("authorized"!==d.status)return"terminal"===d.status?(await o(),void await this.authority.releaseClaim({...s(),reason:"completed"}).catch(()=>{})):void await c({operationId:n.operationId,requestMessageId:n.requestMessageId,request:e.request,fence:e.fence,claimLeaseExpiresAt:e.leaseExpiresAt,runtimeLeaseCredential:t.runtimeLeaseCredential,attempt:prestartAttempt(e.request),outcome:"expired"===d.status?"expired":"cancelled"===d.status?"cancelled":"failed",code:"expired"===d.status?"COMMAND_EXPIRED":"cancelled"===d.status?"OPERATION_CANCELLED":"fenced"===d.status?"INSTANCE_EPOCH_MISMATCH":"UNAUTHORIZED_TARGET"});const m={operationId:n.operationId,requestMessageId:n.requestMessageId,request:e.request,fence:e.fence,claimLeaseExpiresAt:e.leaseExpiresAt,runtimeLeaseCredential:t.runtimeLeaseCredential,attempt:d.attempt},l={...m,attempt:prestartAttempt(e.request)};let h;const p=new AbortController;let E;try{assertCommandCorrelation(e.request,d.attempt.command,t.runtimeEpoch),h=await verifyAndCreateServiceCoreExecutionAttempt({operationId:n.operationId,runtimeEpoch:t.runtimeEpoch,fence:e.fence,authorization:d.attempt.authorization,derivationContext:{...d.attempt.derivationContext,localJournalRevision:u.journalRevisionBeforeAttempt,localPreparedEntryHash:u.preparedEntryHash},verifier:this.authorizationVerifier,abortSignal:p.signal,recordVerifiedAttempt:async t=>{const r=t.request.binding;await this.authorizationJournal.recordBoundary({operationId:n.operationId,expectedRevision:u.revision,preparedEntryHash:u.preparedEntryHash,boundary:{executionBoundaryId:r.executionBoundaryId,boundaryAssertionHash:r.boundaryAssertionHash,executionMode:r.executionMode,fence:e.fence,...r.handoffId?{handoffId:r.handoffId}:{}}})},resolvePorts:async()=>E??=await this.attemptPorts.resolve(m,{getRuntimeLeaseCredential:()=>this.currentRuntimeLeaseCredential(t)})})}catch{return p.abort(),void await c({...l,outcome:"failed",code:"UNAUTHORIZED_TARGET"})}if(!h.ok)return p.abort(),void await c({...l,outcome:"failed",code:"UNAUTHORIZED_TARGET"});let I=!1,C=!1;const f=new RuntimeTransportFailurePolicy;let y,w,M,v,N=!1,A=!1,R=!1,O=!1,T=!1,_=!1,g=!1;const b=new Promise(e=>{v=e}),L=e=>{g||(g=!0,v(e))};let x;const U=()=>{T=!0,p.abort(),M&&!x&&(x=M.cancel().catch(()=>({status:"not_cancellable"})))},q=()=>{I=!0,L("fenced"),U()},S=()=>q();r.addEventListener("abort",S,{once:!0});const P=()=>{const e=this.getLease();e&&e.leaseId===t.leaseId&&e.runtimeEpoch===t.runtimeEpoch||q()},H=setInterval(P,100);H.unref?.();const D=setInterval(()=>{this.authority.renewClaim(s()).then(e=>{f.recordSuccess(),"renewed"===e.status&&e.cancelRequested?(C=!0,L("cancel_requested"),U()):"renewed"!==e.status&&q()}).catch(()=>{f.recordFailure()&&q()})},this.options.claimRenewIntervalMs??2e4);D.unref?.();const j=Date.parse(d.attempt.command.context.executionDeadline)-Date.now(),G=setTimeout(()=>{_=!0,L("deadline"),U()},Math.max(0,Math.min(j,2147483647)));G.unref?.();const z=async e=>{if(!y)return;const r=this.currentConversationRunBoundaryLease(t);await this.finishConversationRunBoundary(m,r,y,e,"recovery"===a?"recovery":"runtime"),y=void 0};try{if(P(),I||r.aborted)return void await i({...m,outcome:"outcome_unknown",code:"INSTANCE_EPOCH_MISMATCH"});if(await this.authority.appendStarted(m),I||r.aborted)return void await i({...m,outcome:"outcome_unknown",code:"INSTANCE_EPOCH_MISMATCH"});if(_)return void await i({...m,outcome:"expired",code:"COMMAND_EXPIRED"});if(C)return void await i({...m,outcome:"cancelled",code:"OPERATION_CANCELLED"});const e=await this.startConversationRunBoundary(m,t,E);if(e?.rejected)return void await i({...m,outcome:"failed",code:e.code});if(y=e,I||r.aborted)throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","runtime authority fenced after the conversation run boundary started");if("recovery"===a&&y)throw new RuntimeCommandError("OUTCOME_UNKNOWN","session.prompt crossed its durable run boundary before recovery");if(_)throw new RuntimeCommandError("COMMAND_EXPIRED","session.prompt expired after the conversation run boundary started");if(C)throw new RuntimeCommandError("OPERATION_CANCELLED","session.prompt was cancelled after the conversation run boundary started");let n;M=this.dispatcher.dispatch(d.attempt.command,h.context),A=!0,T&&U();const s=this.forwardProgress(M.progress,m,()=>I||r.aborted||C||_).catch(e=>{n=e}),c=M.completion.then(e=>(clearTimeout(G),{status:"completed",result:e}),e=>(clearTimeout(G),{status:"failed",error:e}));let u=await Promise.race([c,b.then(e=>({status:"interrupted",reason:e}))]);if("interrupted"===u.status){const e=u.reason;U();if("cancel_requested"===(x?await Promise.race([x,delay(this.options.cancellationGraceMs??1e3).then(()=>({status:"not_cancellable"}))]):{status:"not_cancellable"}).status&&(u=await Promise.race([c,delay(this.options.cancellationGraceMs??1e3).then(()=>({status:"interrupted",reason:e}))])),"interrupted"===u.status)throw new RuntimeCommandError("fenced"===u.reason?"INSTANCE_EPOCH_MISMATCH":"OUTCOME_UNKNOWN","session.prompt execution did not converge after interruption")}if(R=!0,"failed"===u.status)throw u.error;const l=u.result;N=!0;const p="session.prompt"===d.attempt.command.name&&!0===l.requestAborted;if(w=p?"cancelled":"completed",await s,n)throw n;if(await z(w),I||r.aborted)return void await i({...m,outcome:"outcome_unknown",code:"INSTANCE_EPOCH_MISMATCH"});if(_)return void await i({...m,outcome:"outcome_unknown",code:"OUTCOME_UNKNOWN"});if(C&&!p)throw new RuntimeCommandError("OUTCOME_UNKNOWN","cancel request raced a locally completed runtime effect");await this.authority.commitResult({...m,command:d.attempt.command,result:sanitizeServiceResult(d.attempt.command.name,l)}),await o()}catch(e){let t=e;if(y&&(!A||R))try{await z(w??(C||_?"cancelled":"failed"))}catch(r){t=new RuntimeCommandError("OUTCOME_UNKNOWN",`conversation run terminal outcome is unknown: ${errorText(r)}`,void 0,{cause:e})}if(N&&!isUncertainRuntimeError(t)&&(t=new RuntimeCommandError("OUTCOME_UNKNOWN",`runtime effect completed before its terminal receipt: ${errorText(t)}`,void 0,{cause:e})),y)return void(O=!0);const r=serviceRuntimeFailureCode(t),a="OUTCOME_UNKNOWN"===r||"INSTANCE_EPOCH_MISMATCH"===r||I||A&&(C||_),n="COMMAND_EXPIRED"===r||!A&&_,o=!A&&C;await i({...m,outcome:a?"outcome_unknown":n?"expired":o?"cancelled":"failed",code:"INSTANCE_EPOCH_MISMATCH"===r||I?"INSTANCE_EPOCH_MISMATCH":a?"OUTCOME_UNKNOWN":n?"COMMAND_EXPIRED":o?"OPERATION_CANCELLED":r??"RUNTIME_EXECUTION_FAILED"})}finally{clearInterval(H),clearInterval(D),clearTimeout(G),r.removeEventListener("abort",S),p.abort(),await this.authority.releaseClaim({...s(),reason:r.aborted||O?"worker_shutdown":"completed"}).catch(()=>{})}}async startConversationRunBoundary(e,t,r){const a=e.attempt.command;if("session.prompt"!==a.name)return;const n=r?.conversationRunBoundary;if(!n)throw new RuntimeCommandError("INVALID_PARAMS","Service session.prompt lacks its conversation run boundary");const o=a.context.conversation,i=await n.boundary.start({operationId:e.operationId,requestMessageId:e.requestMessageId,conversationId:o.runtimeConversationUid,historyGeneration:n.historyGeneration,runtimeRunId:a.params.runtimeRunId,lease:exactRunBoundaryLease(t)});if("rejected"===i.status)return{rejected:!0,code:i.reason};if(i.historyGeneration!==n.historyGeneration)throw new RuntimeCommandError("OUTCOME_UNKNOWN","conversation run boundary changed history generation");return{boundary:n.boundary,historyGeneration:n.historyGeneration,activeRunRegistrationId:i.activeRunRegistrationId,runtimeRunId:a.params.runtimeRunId}}currentRuntimeLeaseCredential(e){const t=this.getLease();if(!t||t.leaseId!==e.leaseId||t.runtimeEpoch!==e.runtimeEpoch)throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","runtime lease changed before deferred resource redemption");return t.runtimeLeaseCredential}currentConversationRunBoundaryLease(e){const t=this.getLease();if(!t||t.leaseId!==e.leaseId||t.runtimeEpoch!==e.runtimeEpoch||t.handlerIdentity!==e.handlerIdentity)throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","runtime lease changed before conversation run convergence");return t}async finishConversationRunBoundary(e,t,r,a,n){const o=e.attempt.command.context;if("conversation"!==o.scope)throw new RuntimeCommandError("OUTCOME_UNKNOWN","conversation run boundary lost its target");const i=await r.boundary.finish({activeRunRegistrationId:r.activeRunRegistrationId,operationId:e.operationId,requestMessageId:e.requestMessageId,conversationId:o.conversation.runtimeConversationUid,historyGeneration:r.historyGeneration,runtimeRunId:r.runtimeRunId,terminalState:a,source:n,lease:exactRunBoundaryLease(t)});if("rejected"===i.status||i.activeRunRegistrationId!==r.activeRunRegistrationId)throw new RuntimeCommandError("OUTCOME_UNKNOWN",`conversation run finish rejected: ${"rejected"===i.status?i.reason:"registration_mismatch"}`)}async forwardProgress(e,t,r){for await(const a of e){if(r())return;await this.authority.appendProgress({...t,progress:a})}}}function exactRunBoundaryLease(e){return{leaseId:e.leaseId,handlerIdentity:e.handlerIdentity,runtimeEpoch:e.runtimeEpoch,runtimeLeaseCredential:e.runtimeLeaseCredential}}function serviceRuntimeFailureCode(e){const t=e?.code;return t&&["OUTCOME_UNKNOWN","INSTANCE_EPOCH_MISMATCH","COMMAND_EXPIRED","OPERATION_CANCELLED","IDEMPOTENCY_CONFLICT","UNAUTHORIZED_TARGET","AGENT_DEFAULT_MODEL_NOT_CONFIGURED"].includes(t)?t:void 0}function isUncertainRuntimeError(e){return e instanceof RuntimeCommandError&&("OUTCOME_UNKNOWN"===e.code||"INSTANCE_EPOCH_MISMATCH"===e.code)}function errorText(e){return e instanceof Error?e.message:String(e)}export function sanitizeServiceResult(e,t){if("cron.status"!==e||!t||"object"!=typeof t)return t;const r=t;return{enabled:r.enabled,jobCount:r.jobCount,..."number"==typeof r.nextWakeAtMs?{nextWakeAtMs:r.nextWakeAtMs}:{}}}function assertCommandCorrelation(e,t,r){if(e.operationId!==t.context.operationId||e.payload.paramsHash!==t.context.paramsHash||t.context.dispatchEpoch!==r||e.payload.command.name!==t.name||!sessionSetModelMappingMatches(e.payload.request,t))throw new Error("runtime invocation command correlation failed")}function prestartAttempt(e){return{command:e.payload.command,executionBoundaryId:"prestart",boundaryAssertionHash:e.payload.commandHash,executionMode:"start",validationContext:{},authorization:{},derivationContext:{}}}const aborted=Symbol("aborted");function waitForAbort(e,t){return t?t.aborted?(e.catch(()=>{}),Promise.resolve(aborted)):new Promise((r,a)=>{let n=!1;const o=()=>{n||(n=!0,r(aborted))};t.addEventListener("abort",o,{once:!0}),e.then(e=>{n||(n=!0,t.removeEventListener("abort",o),r(e))},e=>{n||(n=!0,t.removeEventListener("abort",o),a(e))})}):e}const delay=(e,t)=>new Promise(r=>{if(t?.aborted)return r();const a=()=>{clearTimeout(n),r()},n=setTimeout(()=>{t?.removeEventListener("abort",a),r()},e);t?.addEventListener("abort",a,{once:!0})});
|
|
1
|
+
import{randomUUID}from"node:crypto";import{verifyAndCreateServiceCoreExecutionAttempt}from"./core-execution-attempt-context.js";import{RuntimeCommandError}from"./runtime-command-dispatcher.js";import{RuntimeClaimAuthorityProtocolError}from"./message-service-runtime-claim-authority.js";import{sessionSetModelMappingMatches}from"./session-set-model-mapping.js";import{RuntimeTransportFailurePolicy}from"@beeos-ai/cloud-harness-sdk";export class MsRuntimeRpcAdapter{dispatcher;authority;authorizationVerifier;attemptPorts;authorizationJournal;getLease;options;controller;running;constructor(e,t,r,a,n,o,i){this.dispatcher=e,this.authority=t,this.authorizationVerifier=r,this.attemptPorts=a,this.authorizationJournal=n,this.getLease=o,this.options=i}start(){if(this.running)return;this.controller=new AbortController;const e=this.loop(this.controller.signal).finally(()=>{this.running===e&&(this.running=void 0)});this.running=e}async stop(e){const t=this.running;if(this.controller?.abort(),!t)return;await waitForAbort(t,e)===aborted&&this.running===t&&(this.running=void 0)}journalLineage(){return this.options.getJournalLineage?.()??{journalStoreId:this.options.journalStoreId,journalGeneration:this.options.journalGeneration}}async loop(e){let t=randomUUID(),r="",a="";for(;!e.aborted;){const n=this.getLease();if(!n){await delay(this.options.pollDelayMs??1e3,e);continue}const o=this.journalLineage(),i=`${n.instanceId}\n${n.runtimeEpoch}\n${this.options.handlerIdentity}\n${o.journalStoreId}\n${o.journalGeneration}`;if(r&&r!==i&&(t=randomUUID()),r=i,a!==i)try{const t=await this.authorizationJournal.listRecoverable(n.runtimeEpoch);for(const r of t){if(e.aborted||this.getLease()?.leaseId!==n.leaseId)break;if(!await this.recoverExact({operationId:r.operationId,requestMessageId:r.requestMessageId,dispatchEpoch:r.runtimeEpoch},n,e))throw new Error("durable runtime invocation is still owned by another claim")}a=i}catch{await delay(this.options.pollDelayMs??1e3,e);continue}let s;try{const r=this.authority.claimNext({claimRequestId:t,instanceId:n.instanceId,handlerIdentity:this.options.handlerIdentity,runtimeEpoch:n.runtimeEpoch,journalStoreId:o.journalStoreId,journalGeneration:o.journalGeneration,runtimeLeaseCredential:n.runtimeLeaseCredential}),a=await waitForAbort(r,e);if(a===aborted)return;s=a}catch(t){if(e.aborted)return;if(t instanceof RuntimeClaimAuthorityProtocolError)return;await delay(this.options.pollDelayMs??1e3,e);continue}if(e.aborted)return;t=randomUUID(),"empty"!==s.status?"fenced"!==s.status?await this.handleClaimed(s,n,e,"start").catch(()=>{}):await delay(this.options.pollDelayMs??1e3,e):await delay(Math.max(s.retryAfterMs,this.options.pollDelayMs??0),e)}}async recoverExact(e,t,r){if(e.dispatchEpoch!==t.runtimeEpoch)throw new Error("recovery candidate runtime epoch mismatch");const a=this.journalLineage(),n=await this.authority.claimExact({operationId:e.operationId,requestMessageId:e.requestMessageId,handlerIdentity:this.options.handlerIdentity,dispatchEpoch:e.dispatchEpoch,runtimeEpoch:t.runtimeEpoch,journalStoreId:a.journalStoreId,journalGeneration:a.journalGeneration,runtimeLeaseCredential:t.runtimeLeaseCredential});return"terminal"===n.status?(await this.authorizationJournal.markTerminal(e.operationId).catch(()=>{}),!0):"claimed"===n.status&&(await this.handleClaimed(n,t,r,"recovery"),!0)}async handleClaimed(e,t,r,a="start"){const n={operationId:e.request.operationId,requestMessageId:e.request.messageId,dispatchEpoch:e.request.payload.command.context.dispatchEpoch},o=async()=>{await this.authorizationJournal.markTerminal(n.operationId).catch(()=>{})},i=async e=>{await this.authority.commitFailure(e),await o()},s=()=>{const r=this.getLease(),a=r?.leaseId===t.leaseId&&r.runtimeEpoch===t.runtimeEpoch?r.runtimeLeaseCredential:t.runtimeLeaseCredential;return{operationId:n.operationId,requestMessageId:n.requestMessageId,...e.fence,runtimeLeaseCredential:a}},c=async e=>{try{await i(e)}finally{await this.authority.releaseClaim({...s(),reason:"claim_rejected"}).catch(()=>{})}};if(e.cancelRequested)return await i({operationId:n.operationId,requestMessageId:n.requestMessageId,request:e.request,fence:e.fence,claimLeaseExpiresAt:e.leaseExpiresAt,runtimeLeaseCredential:t.runtimeLeaseCredential,attempt:prestartAttempt(e.request),outcome:"cancelled",code:"OPERATION_CANCELLED"}),void await this.authority.releaseClaim({...s(),reason:"cancelled"});let u;try{u=await this.authorizationJournal.prepare({operationId:n.operationId,requestMessageId:n.requestMessageId,method:e.request.payload.request.method,commandHash:e.request.payload.commandHash,runtimeEpoch:t.runtimeEpoch,journalStoreId:e.fence.journalStoreId,journalGeneration:e.fence.journalGeneration})}catch{return void await c({operationId:n.operationId,requestMessageId:n.requestMessageId,request:e.request,fence:e.fence,claimLeaseExpiresAt:e.leaseExpiresAt,runtimeLeaseCredential:t.runtimeLeaseCredential,attempt:prestartAttempt(e.request),outcome:"failed",code:"UNAUTHORIZED_TARGET"}).catch(()=>{})}const d=await this.authority.authorize({request:e.request,fence:e.fence,lease:t,journal:u});if("authorized"!==d.status)return"terminal"===d.status?(await o(),void await this.authority.releaseClaim({...s(),reason:"completed"}).catch(()=>{})):void await c({operationId:n.operationId,requestMessageId:n.requestMessageId,request:e.request,fence:e.fence,claimLeaseExpiresAt:e.leaseExpiresAt,runtimeLeaseCredential:t.runtimeLeaseCredential,attempt:prestartAttempt(e.request),outcome:"expired"===d.status?"expired":"cancelled"===d.status?"cancelled":"failed",code:"expired"===d.status?"COMMAND_EXPIRED":"cancelled"===d.status?"OPERATION_CANCELLED":"fenced"===d.status?"INSTANCE_EPOCH_MISMATCH":"UNAUTHORIZED_TARGET"});const m={operationId:n.operationId,requestMessageId:n.requestMessageId,request:e.request,fence:e.fence,claimLeaseExpiresAt:e.leaseExpiresAt,runtimeLeaseCredential:t.runtimeLeaseCredential,attempt:d.attempt},l={...m,attempt:prestartAttempt(e.request)};let h;const p=new AbortController;let E;try{assertCommandCorrelation(e.request,d.attempt.command,t.runtimeEpoch),h=await verifyAndCreateServiceCoreExecutionAttempt({operationId:n.operationId,runtimeEpoch:t.runtimeEpoch,fence:e.fence,authorization:d.attempt.authorization,derivationContext:{...d.attempt.derivationContext,localJournalRevision:u.journalRevisionBeforeAttempt,localPreparedEntryHash:u.preparedEntryHash},verifier:this.authorizationVerifier,abortSignal:p.signal,recordVerifiedAttempt:async t=>{const r=t.request.binding;await this.authorizationJournal.recordBoundary({operationId:n.operationId,expectedRevision:u.revision,preparedEntryHash:u.preparedEntryHash,boundary:{executionBoundaryId:r.executionBoundaryId,boundaryAssertionHash:r.boundaryAssertionHash,executionMode:r.executionMode,fence:e.fence,...r.handoffId?{handoffId:r.handoffId}:{}}})},resolvePorts:async()=>E??=await this.attemptPorts.resolve(m,{getRuntimeLeaseCredential:()=>this.currentRuntimeLeaseCredential(t)})})}catch{return p.abort(),void await c({...l,outcome:"failed",code:"UNAUTHORIZED_TARGET"})}if(!h.ok)return p.abort(),void await c({...l,outcome:"failed",code:"UNAUTHORIZED_TARGET"});let I=!1,C=!1;const f=new RuntimeTransportFailurePolicy;let y,w,M,v,N=!1,A=!1,R=!1,O=!1,T=!1,_=!1,b=!1;const g=new Promise(e=>{v=e}),L=e=>{b||(b=!0,v(e))};let x;const U=()=>{T=!0,p.abort(),M&&!x&&(x=M.cancel().catch(()=>({status:"not_cancellable"})))},q=()=>{I=!0,L("fenced"),U()},S=()=>q();r.addEventListener("abort",S,{once:!0});const P=()=>{const e=this.getLease();e&&e.leaseId===t.leaseId&&e.runtimeEpoch===t.runtimeEpoch||q()},H=setInterval(P,100);H.unref?.();const D=setInterval(()=>{this.authority.renewClaim(s()).then(e=>{f.recordSuccess(),"renewed"===e.status&&e.cancelRequested?(C=!0,L("cancel_requested"),U()):"renewed"!==e.status&&q()}).catch(()=>{f.recordFailure()&&q()})},this.options.claimRenewIntervalMs??2e4);D.unref?.();const j=Date.parse(d.attempt.command.context.executionDeadline)-Date.now(),G=setTimeout(()=>{_=!0,L("deadline"),U()},Math.max(0,Math.min(j,2147483647)));G.unref?.();const z=async e=>{if(!y)return;const r=this.currentConversationRunBoundaryLease(t);await this.finishConversationRunBoundary(m,r,y,e,"recovery"===a?"recovery":"runtime"),y=void 0};try{if(P(),I||r.aborted)return void await i({...m,outcome:"outcome_unknown",code:"INSTANCE_EPOCH_MISMATCH"});if(await this.authority.appendStarted(m),I||r.aborted)return void await i({...m,outcome:"outcome_unknown",code:"INSTANCE_EPOCH_MISMATCH"});if(_)return void await i({...m,outcome:"expired",code:"COMMAND_EXPIRED"});if(C)return void await i({...m,outcome:"cancelled",code:"OPERATION_CANCELLED"});const e=await this.startConversationRunBoundary(m,t,E);if(e?.rejected)return void await i({...m,outcome:"failed",code:e.code});if(y=e,I||r.aborted)throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","runtime authority fenced after the conversation run boundary started");if("recovery"===a&&y)throw new RuntimeCommandError("OUTCOME_UNKNOWN","session.prompt crossed its durable run boundary before recovery");if(_)throw new RuntimeCommandError("COMMAND_EXPIRED","session.prompt expired after the conversation run boundary started");if(C)throw new RuntimeCommandError("OPERATION_CANCELLED","session.prompt was cancelled after the conversation run boundary started");let n;M=this.dispatcher.dispatch(d.attempt.command,h.context),A=!0,T&&U();const s=this.forwardProgress(M.progress,m,()=>I||r.aborted||C||_).catch(e=>{n=e}),c=M.completion.then(e=>(clearTimeout(G),{status:"completed",result:e}),e=>(clearTimeout(G),{status:"failed",error:e}));let u=await Promise.race([c,g.then(e=>({status:"interrupted",reason:e}))]);if("interrupted"===u.status){const e=u.reason;U();if("cancel_requested"===(x?await Promise.race([x,delay(this.options.cancellationGraceMs??1e3).then(()=>({status:"not_cancellable"}))]):{status:"not_cancellable"}).status&&(u=await Promise.race([c,delay(this.options.cancellationGraceMs??1e3).then(()=>({status:"interrupted",reason:e}))])),"interrupted"===u.status)throw new RuntimeCommandError("fenced"===u.reason?"INSTANCE_EPOCH_MISMATCH":"OUTCOME_UNKNOWN","session.prompt execution did not converge after interruption")}if(R=!0,"failed"===u.status)throw u.error;const l=u.result;N=!0;const p="session.prompt"===d.attempt.command.name&&!0===l.requestAborted;if(w=p?"cancelled":"completed",await s,n)throw n;if(await z(w),I||r.aborted)return void await i({...m,outcome:"outcome_unknown",code:"INSTANCE_EPOCH_MISMATCH"});if(_)return void await i({...m,outcome:"outcome_unknown",code:"OUTCOME_UNKNOWN"});if(C&&!p)throw new RuntimeCommandError("OUTCOME_UNKNOWN","cancel request raced a locally completed runtime effect");await this.authority.commitResult({...m,command:d.attempt.command,result:sanitizeServiceResult(d.attempt.command.name,l)}),await o()}catch(e){let t=e;if(y&&(!A||R))try{await z(w??(C||_?"cancelled":"failed"))}catch(r){t=new RuntimeCommandError("OUTCOME_UNKNOWN",`conversation run terminal outcome is unknown: ${errorText(r)}`,void 0,{cause:e})}if(N&&!isUncertainRuntimeError(t)&&(t=new RuntimeCommandError("OUTCOME_UNKNOWN",`runtime effect completed before its terminal receipt: ${errorText(t)}`,void 0,{cause:e})),y)return void(O=!0);const r=serviceRuntimeFailureCode(t),a="OUTCOME_UNKNOWN"===r||"INSTANCE_EPOCH_MISMATCH"===r||I||A&&(C||_),n="COMMAND_EXPIRED"===r||!A&&_,o=!A&&C;await i({...m,outcome:a?"outcome_unknown":n?"expired":o?"cancelled":"failed",code:"INSTANCE_EPOCH_MISMATCH"===r||I?"INSTANCE_EPOCH_MISMATCH":a?"OUTCOME_UNKNOWN":n?"COMMAND_EXPIRED":o?"OPERATION_CANCELLED":r??"RUNTIME_EXECUTION_FAILED"})}finally{clearInterval(H),clearInterval(D),clearTimeout(G),r.removeEventListener("abort",S),p.abort(),await this.authority.releaseClaim({...s(),reason:r.aborted||O?"worker_shutdown":"completed"}).catch(()=>{})}}async startConversationRunBoundary(e,t,r){const a=e.attempt.command;if("session.prompt"!==a.name)return;const n=r?.conversationRunBoundary;if(!n)throw new RuntimeCommandError("INVALID_PARAMS","Service session.prompt lacks its conversation run boundary");const o=a.context.conversation,i=await n.boundary.start({operationId:e.operationId,requestMessageId:e.requestMessageId,conversationId:o.runtimeConversationUid,historyGeneration:n.historyGeneration,runtimeRunId:a.params.runtimeRunId,lease:exactRunBoundaryLease(t)});if("rejected"===i.status)return{rejected:!0,code:i.reason};if(i.historyGeneration!==n.historyGeneration)throw new RuntimeCommandError("OUTCOME_UNKNOWN","conversation run boundary changed history generation");return{boundary:n.boundary,historyGeneration:n.historyGeneration,activeRunRegistrationId:i.activeRunRegistrationId,runtimeRunId:a.params.runtimeRunId}}currentRuntimeLeaseCredential(e){const t=this.getLease();if(!t||t.leaseId!==e.leaseId||t.runtimeEpoch!==e.runtimeEpoch)throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","runtime lease changed before deferred resource redemption");return t.runtimeLeaseCredential}currentConversationRunBoundaryLease(e){const t=this.getLease();if(!t||t.leaseId!==e.leaseId||t.runtimeEpoch!==e.runtimeEpoch||t.handlerIdentity!==e.handlerIdentity)throw new RuntimeCommandError("INSTANCE_EPOCH_MISMATCH","runtime lease changed before conversation run convergence");return t}async finishConversationRunBoundary(e,t,r,a,n){const o=e.attempt.command.context;if("conversation"!==o.scope)throw new RuntimeCommandError("OUTCOME_UNKNOWN","conversation run boundary lost its target");const i=await r.boundary.finish({activeRunRegistrationId:r.activeRunRegistrationId,operationId:e.operationId,requestMessageId:e.requestMessageId,conversationId:o.conversation.runtimeConversationUid,historyGeneration:r.historyGeneration,runtimeRunId:r.runtimeRunId,terminalState:a,source:n,lease:exactRunBoundaryLease(t)});if("rejected"===i.status||i.activeRunRegistrationId!==r.activeRunRegistrationId)throw new RuntimeCommandError("OUTCOME_UNKNOWN",`conversation run finish rejected: ${"rejected"===i.status?i.reason:"registration_mismatch"}`)}async forwardProgress(e,t,r){for await(const a of e){if(r())return;await this.authority.appendProgress({...t,progress:a})}}}function exactRunBoundaryLease(e){return{leaseId:e.leaseId,handlerIdentity:e.handlerIdentity,runtimeEpoch:e.runtimeEpoch,runtimeLeaseCredential:e.runtimeLeaseCredential}}function serviceRuntimeFailureCode(e){const t=e?.code;return t&&["OUTCOME_UNKNOWN","INSTANCE_EPOCH_MISMATCH","COMMAND_EXPIRED","OPERATION_CANCELLED","IDEMPOTENCY_CONFLICT","UNAUTHORIZED_TARGET","AGENT_DEFAULT_MODEL_NOT_CONFIGURED"].includes(t)?t:void 0}function isUncertainRuntimeError(e){return e instanceof RuntimeCommandError&&("OUTCOME_UNKNOWN"===e.code||"INSTANCE_EPOCH_MISMATCH"===e.code)}function errorText(e){return e instanceof Error?e.message:String(e)}export function sanitizeServiceResult(e,t){if("cron.status"!==e||!t||"object"!=typeof t)return t;const r=t;return{enabled:r.enabled,jobCount:r.jobCount,..."number"==typeof r.nextWakeAtMs?{nextWakeAtMs:r.nextWakeAtMs}:{}}}function assertCommandCorrelation(e,t,r){if(e.operationId!==t.context.operationId||e.payload.paramsHash!==t.context.paramsHash||t.context.dispatchEpoch!==r||e.payload.command.name!==t.name||!sessionSetModelMappingMatches(e.payload.request,t))throw new Error("runtime invocation command correlation failed")}function prestartAttempt(e){return{command:e.payload.command,executionBoundaryId:"prestart",boundaryAssertionHash:e.payload.commandHash,executionMode:"start",validationContext:{},authorization:{},derivationContext:{}}}const aborted=Symbol("aborted");function waitForAbort(e,t){return t?t.aborted?(e.catch(()=>{}),Promise.resolve(aborted)):new Promise((r,a)=>{let n=!1;const o=()=>{n||(n=!0,r(aborted))};t.addEventListener("abort",o,{once:!0}),e.then(e=>{n||(n=!0,t.removeEventListener("abort",o),r(e))},e=>{n||(n=!0,t.removeEventListener("abort",o),a(e))})}):e}const delay=(e,t)=>new Promise(r=>{if(t?.aborted)return r();const a=()=>{clearTimeout(n),r()},n=setTimeout(()=>{t?.removeEventListener("abort",a),r()},e);t?.addEventListener("abort",a,{once:!0})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createCentrifugoRealtimePort,createRuntimeChatClient,createRuntimeChatHttpPort}from"@beeos-ai/cloud-harness-sdk";import{NativeSessionNewBridge,nativeSessionNewConversationCreator}from"./native-session-new-bridge.js";const MESSAGE_CREATED="message.created";export function nativeCloudChatAuthorityFromRuntimeAuthority(e,t=Date.now){const n=e=>{if(!e||!e.runtimeLeaseCredential)return null;const n=Date.parse(e.leaseExpiresAt);return!Number.isFinite(n)||n<=t()?null:{instanceId:e.instanceId,handlerIdentity:e.handlerIdentity,runtimeEpoch:e.runtimeEpoch,leaseId:e.leaseId,runtimeLeaseCredential:e.runtimeLeaseCredential,leaseExpiresAt:e.leaseExpiresAt}};return{currentLease:()=>n(e.authorityLease),subscribeAuthority:t=>e.subscribeAuthority(e=>t(n(e)))}}export function createNativeCloudChatComposition(e){const t=e.now??Date.now,n=e.http??createRuntimeChatHttpPort({baseUrl:e.serviceUrl,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},now:t}),s=e.realtime??createCentrifugoRealtimePort(),i=createRuntimeChatClient({authority:{currentLease:()=>e.authority.currentLease(),subscribeLease:t=>e.authority.subscribeAuthority(t)},http:n,realtime:s,now:t,...e.reconnectDelayMs?{reconnectDelayMs:e.reconnectDelayMs}:{},...e.logger?{logger:e.logger}:{}}),o=new NativeCloudChatAdapterImpl({client:i,...e.logger?{logger:e.logger}:{}});return{client:i,adapter:o,http:n,sessionNew:new NativeSessionNewBridge({client:i,...e.logger?{logger:e.logger}:{}}),sessionNewConversation:nativeSessionNewConversationCreator(i,e.logger),disconnect:async()=>{await o.disconnect(),await i.disconnect()},dispose:()=>{o.dispose(),i.dispose()}}}class NativeCloudChatAdapterImpl{deps;messages;projections=new Map;conversationProjections=new Map;storeListeners=new Set;inboundListeners=new Set;connection="disconnected";constructor(e){this.deps=e,this.messages={startStream:e=>this.startStream(e),getEnvelope:async(e,t)=>await this.getEnvelope(e,t)},this.deps.client.on("message",e=>this.admitInbound(e)),this.deps.client.on("connection",e=>{this.connection=e,this.publish()}),this.deps.client.on("error",e=>{this.deps.logger?.warn?.(`[native-cloud-chat] realtime error: ${e instanceof Error?e.message:String(e)}`)})}async connect(){try{await this.deps.client.connect()}catch(e){throw this.connection="disconnected",this.publish(),e}}async disconnect(){this.connection="disconnected",await this.deps.client.disconnect(),this.publish()}dispose(){this.storeListeners.clear(),this.inboundListeners.clear(),this.deps.client.dispose()}listen(e,t){const n=e.eventTypes;return n&&!n.includes(MESSAGE_CREATED)?()=>{}:(this.inboundListeners.add(t),()=>{this.inboundListeners.delete(t)})}subscribe(e){return this.storeListeners.add(e),()=>{this.storeListeners.delete(e)}}getSnapshot(){const e={};for(const[t,n]of this.projections)e[t]=n;const t={};for(const[e,n]of this.conversationProjections)t[e]=n;return{connection:this.connection,messages:e,conversations:t}}admitInbound(e){const t=toInboundProjection(e);this.projections.set(t.id,t),this.publish();for(const e of[...this.inboundListeners])e(t)}publish(){for(const e of[...this.storeListeners])e()}startStream(e){return new NativeHandlerReplyStream(this.deps.client.messages.startStream({conversationId:e.conversationId,id:e.clientMessageId,type:e.type,content:e.content,...e.replyTo?{replyTo:e.replyTo}:{}}))}async getEnvelope(e,t){const n=(await this.deps.client.history(e)).messages.find(e=>e.id===t);return{state:"string"==typeof n?.state?n.state:"outcome_unknown"}}}class NativeHandlerReplyStream{inner;constructor(e){this.inner=e}get id(){return this.inner.id}get isTerminated(){return this.inner.isTerminated}get parts(){return this.inner.parts}async opened(){const e=asRecord(await this.inner.opened()),t="string"==typeof e?.messageId&&e.messageId.length>0?e.messageId:this.inner.id;return"string"==typeof e?.outcome?{messageId:t,outcome:e.outcome}:{messageId:t}}appendBody(e){this.inner.appendBody(e)}setBody(e){this.inner.setBody(e)}addPart(e){this.inner.addPart(e)}replacePart(e,t){this.inner.replacePart(e,t)}appendToolResult(e,t,n){this.inner.addToolResult({type:"tool_result",tool_use_id:e,content:t,...n?{is_error:!0}:{}})}finalize(e){return this.inner.finalize(e)}fail(e){return this.inner.fail(e)}cancel(e){return this.inner.cancel(e)}}export function toInboundProjection(e){const t=asRecord(e)??{},n="string"==typeof t.body?t.body:"",s=Array.isArray(t.parts)?t.parts:void 0,i="string"==typeof t.state?t.state:void 0,o="string"==typeof t.stopReason?t.stopReason:void 0,r="string"==typeof t.createdAt?t.createdAt:void 0,a="string"==typeof t.updatedAt?t.updatedAt:r,c="string"==typeof t.offset?t.offset:"0";return{...t,id:e.id,conversationId:e.conversationId,type:e.type,content:e.content??{},...e.senderId?{senderId:e.senderId}:{},...e.replyTo?{replyTo:e.replyTo}:{},body:n,...s?{parts:s}:{},...i?{state:i}:{},...o?{stopReason:o}:{},...r?{createdAt:r}:{},...a?{updatedAt:a}:{},offset:c}}function asRecord(e){return null===e||"object"!=typeof e||Array.isArray(e)?void 0:e}export function historyToInboundProjection(e){return toInboundProjection(e)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
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 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 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=createNativeOutputFileAttempt({operationId:s.operationId,requestMessageId:s.requestMessageId,paramsHash:s.paramsHash,activeRunRegistrationId:v,getLease:()=>(m(),t.getLease()),assertAttempt:m,signal:N.signal}),T=setTimeout(()=>N.abort(nativePromptExecutionDeadlineReason),Math.max(0,Math.min(Date.parse(s.executionDeadlineAt)-3e4-Date.now(),2147483647)));T.unref?.();try{await dispatchImInboundPrompt({...t.host,runtimeRunId:o.runtimeRunId,onNativeAgentRunStart:e=>q.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(T),q.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 P;try{await A.completion}catch(e){P=e}if(m(),!y)throw new RuntimeCommandError("OUTCOME_UNKNOWN",void 0!==P?"native host/abort/drain did not converge":"native kernel settled without verified original reply terminal",void 0,{cause:P??U});const S=this.terminal(y,r),L=await c();g.assertTerminalSnapshot(L);const x="completed"===L.state?"completed":"cancelled"===L.state?"cancelled":"failed",H=await t.runBoundary.finish({...f,activeRunRegistrationId:v,terminalState:x,source:"runtime",lease:I()});if(m(),"finished"!==H.status&&"idempotent"!==H.status||H.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"===S.outcome?"effect_committed":"failed",result:S.result}),m(),{request:s,...S}}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}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{CLOUD_GATEWAY_RUNTIME_ROUTES}from"@beeos-ai/cloud-harness-sdk";import{runtimeLeaseHttp}from"./message-service-runtime-authenticated-fetch.js";const nativeJson=JSON,object=e=>null!==e&&"object"==typeof e&&!Array.isArray(e),integerSource=e=>{if(!nativeJson.isRawJSON(e))return null;const t=JSON.stringify(e);return/^(0|[1-9][0-9]*)$/.test(t)&&BigInt(t)<=9223372036854775807n?t:null},nonempty=e=>"string"==typeof e&&e.length>0;export class NativeInputFilesHttpError extends Error{status;code;requestId;metadata;constructor(e,t,r,n){super(`native input Files resolve failed (${e})`),this.status=e,this.code=t,this.requestId=r,this.metadata=n}}const evidenceText=e=>"string"==typeof e&&/^[A-Za-z0-9_.:-]{1,128}$/.test(e);function selectedHttpError(e,t){const r=object(t)&&object(t.error)?t.error:void 0,n={};if(r&&object(r.metadata))for(const e of["operationId","requestMessageId","paramsHash","taskId","partIndex","clearIntentId","activeRunRegistrationId","historyGeneration","runtimeEpoch"]){const t=r.metadata[e];(evidenceText(t)||nativeJson.isRawJSON(t)&&null!==integerSource(t))&&(n[e]=t)}return new NativeInputFilesHttpError(e,r&&evidenceText(r.code)?r.code:void 0,object(t)&&evidenceText(t.request_id)?t.request_id:void 0,Object.keys(n).length?n:void 0)}export class NativeInputFilesHttpClient{getLease;transport;origin;constructor(e,t,r){this.getLease=t,this.transport=r;const n=new URL(e);if(!["http:","https:"].includes(n.protocol)||n.username||n.password||"/"!==n.pathname||n.search||n.hash)throw new Error("native input Files origin invalid");this.origin=n.origin}async resolve(e){const t=()=>{const t=this.getLease();if(!t||t.instanceId!==e.lease.instanceId||t.handlerIdentity!==e.lease.handlerIdentity||t.leaseId!==e.lease.leaseId||t.runtimeEpoch!==e.lease.runtimeEpoch||!t.runtimeLeaseCredential||Date.parse(t.leaseExpiresAt)<=Date.now())throw new Error("native input Files lease fenced");return t};if(!Number.isSafeInteger(e.partIndex)||e.partIndex<0)throw new Error("native input Files part index invalid");const r=t(),n=await runtimeLeaseHttp(this.origin,(e,t)=>this.transport(e,t??{})).postJson(CLOUD_GATEWAY_RUNTIME_ROUTES.inputFilesResolve(e.operationId),{runtimeLeaseCredential:r.runtimeLeaseCredential},{requestMessageId:e.requestMessageId,paramsHash:e.paramsHash,partIndex:e.partIndex},void 0,e.signal);if(t(),n.url&&new URL(n.url).origin!==this.origin)throw new Error("native input Files response origin changed");if("function"!=typeof nativeJson.rawJSON||"function"!=typeof nativeJson.isRawJSON)throw new Error("native numeric JSON source required");const i=await n.text();let s;try{s=nativeJson.parse(i,(e,t,r)=>{if("number"!=typeof t)return t;if(!r?.source)throw new Error("native numeric JSON source required");return nativeJson.rawJSON(r.source)})}catch(e){if(!(e instanceof SyntaxError))throw e;if(!n.ok)throw new NativeInputFilesHttpError(n.status);throw new Error("native input Files response JSON invalid")}if(t(),!n.ok)throw selectedHttpError(n.status,s);if(!object(s)||s.operationId!==e.operationId||s.requestMessageId!==e.requestMessageId||s.paramsHash!==e.paramsHash||s.taskId!==e.operationId||integerSource(s.partIndex)!==`${e.partIndex}`||!object(s.file)||!object(s.download))throw new Error("native input Files response binding invalid");const o=s.file,a=s.download,d=integerSource(a.size_bytes),c=integerSource(o.size_bytes),u=integerSource(o.resource_version);if(!nonempty(o.file_id)||!nonempty(o.filename)||"ready"!==o.status||null===u||null===c||!nonempty(o.content_type)||"download"!==a.direction||a.file_id!==o.file_id||"GET"!==a.http_method||!nonempty(a.url)||!nonempty(a.expires_at)||!nonempty(a.content_type)||null===d||d!==c||a.content_type!==o.content_type||a.checksum_sha256!==o.checksum_sha256||void 0!==a.checksum_sha256&&"string"!=typeof a.checksum_sha256||!object(a.required_headers)||Object.values(a.required_headers).some(e=>"string"!=typeof e))throw new Error("native input Files descriptor invalid");const p={...a,direction:"download",file_id:o.file_id,url:a.url,http_method:"GET",required_headers:a.required_headers,expires_at:a.expires_at,content_type:a.content_type,size_bytes:d,...void 0!==a.checksum_sha256?{checksum_sha256:a.checksum_sha256}:{}};return{filename:o.filename,download:p,file:o}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createWriteStream}from"node:fs";import{mkdir,mkdtemp,rm}from"node:fs/promises";import{join,basename}from"node:path";import{createHash}from"node:crypto";import{Readable,Transform}from"node:stream";import{pipeline}from"node:stream/promises";export async function downloadNativeInputFile(e){const t=e.download;if("download"!==t.direction||t.file_id!==e.fileId||"GET"!==t.http_method||!/^(0|[1-9][0-9]*)$/.test(t.size_bytes)||!t.content_type||!Number.isFinite(Date.parse(t.expires_at))||Date.parse(t.expires_at)<=Date.now())throw new Error("native input file descriptor invalid or expired");let r;try{r=new URL(t.url)}catch(e){if(!(e instanceof TypeError))throw e;throw new Error("native input file transfer URL invalid")}if("https:"!==r.protocol&&"http:"!==r.protocol||r.username||r.password)throw new Error("native input file transfer URL invalid");if(void 0!==t.checksum_sha256&&!/^[0-9a-f]{64}$/.test(t.checksum_sha256))throw new Error("native input file checksum invalid");e.assertAttempt();const i=e.signal,a=await fetch(r,{method:t.http_method,headers:t.required_headers,signal:i,redirect:"error"});if(!a.ok||!a.body)throw new Error(`native input file download failed (${a.status})`);e.assertAttempt();const o=process.env.OPENCLAW_HOME??join(process.env.HOME??"/home/node",".openclaw"),n=join(o,"workspace","uploads");await mkdir(n,{recursive:!0});const s=await mkdtemp(join(n,"native-input-")),p=basename(e.filename).replace(/[^\p{L}\p{N}._-]/gu,"_"),c=join(s,p&&"."!==p&&".."!==p?p:"attachment");let m=0n;const d=BigInt(t.size_bytes),l=createHash("sha256"),f=new Transform({transform(e,t,r){m+=BigInt(e.byteLength),m>d?r(new Error("native input file size mismatch")):(l.update(e),r(null,e))}});try{const r=a.body.getReader(),o=async function*(){try{for(;;){const e=await r.read();if(e.done)return;yield e.value}}finally{await r.cancel(),r.releaseLock()}};if(await pipeline(Readable.from(o()),f,createWriteStream(c,{flags:"wx",mode:384}),{signal:i}),e.assertAttempt(),m!==d||void 0!==t.checksum_sha256&&l.digest("hex")!==t.checksum_sha256)throw new Error("native input file bytes do not match confirmed descriptor");return{path:c,mimeType:t.content_type}}catch(e){throw await rm(s,{recursive:!0,force:!0}),e}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const runs=new Map,tools=new Map,consumed=new Set;export function createNativeOutputFileAttempt(t){let e,o=!0;const s={...t,assertAttempt(){if(!o)throw new Error("native output file attempt finished");t.signal.throwIfAborted(),t.assertAttempt();const e=t.getLease();if(!e.runtimeLeaseCredential||!Number.isFinite(Date.parse(e.leaseExpiresAt))||Date.parse(e.leaseExpiresAt)<=Date.now())throw new Error("native output file lease fenced")},getLease:()=>(s.assertAttempt(),t.getLease())};return{bindHostRun(t){if(s.assertAttempt(),!t||void 0!==e||runs.has(t))throw new Error("native output file Host run binding ambiguous");e=t,runs.set(t,s)},close(){o=!1,e&&runs.get(e)===s&&runs.delete(e);for(const[t,e]of tools)e.assertAttempt===s.assertAttempt&&tools.delete(t);for(const e of consumed)e.startsWith(t.operationId+"\0")&&consumed.delete(e)}}}export function prepareNativeOutputTool(t,e){if(!t||!e)throw new Error("native output file trusted Host tool binding missing");const o=runs.get(t);if(!o)throw new Error("native output file trusted run missing");o.assertAttempt();const s=o.operationId+"\0"+e;if(tools.has(e)||consumed.has(s))throw new Error("native output file tool binding ambiguous or consumed");tools.set(e,{...o,toolCallId:e})}export function consumeNativeOutputTool(t){const e=tools.get(t);if(tools.delete(t),!e)throw new Error("native output file tool capability missing");return e.assertAttempt(),consumed.add(e.operationId+"\0"+t),e}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isCloudRuntimeSubject,RUNTIME_HASH_DOMAINS,runtimeCloudCallerIntentPayload,runtimeCloudIdempotencyFingerprintPayload}from"@beeos-ai/beeos-types/runtime";import{runtimeMessageHash,semanticEqual}from"./runtime-message-channel-contract.js";import{RuntimeCommandError}from"./runtime-command-dispatcher.js";import{isDeepStrictEqual}from"node:util";const verifiedPrompts=new WeakMap;export function retainedVerifiedNativePrompt(e){if(!e||"object"!=typeof e)return null;const t=verifiedPrompts.get(e);return t&&isDeepStrictEqual(e,t)?structuredClone(t):null}const object=e=>!!e&&"object"==typeof e&&!Array.isArray(e),nonempty=e=>"string"==typeof e&&!!e,digest=e=>"string"==typeof e&&/^[0-9a-f]{64}$/.test(e),decimal=e=>"string"==typeof e&&/^(0|[1-9][0-9]*)$/.test(e),exact=(e,t)=>Object.keys(e).sort().join("\0")===t.sort().join("\0"),fail=()=>{throw new RuntimeCommandError("INVALID_PARAMS","native prompt signed binding invalid")};export function verifyNativePromptAuthority(e){const t=e.request,a=e.decoded?.claims;if(!(object(t)&&object(a)&&object(t.request)&&object(t.command)&&object(t.command.context)&&object(t.command.params)&&object(t.request.params)))return fail();const n=t.request.params,r=t.command.context,o=n.runtimeLease;if(!(exact(t,["schemaVersion","authorityRealm","cloudSubject","operationId","requestMessageId","requestHash","paramsHash","commandHash","idempotencyKeyHash","idempotencyFingerprint","callerIntentHash","instanceId","leaseId","runtimeHandlerIdentity","dispatchEpoch","executionGrantHash","claimDeadlineAt","executionDeadlineAt","createdAt","method","request","command","callerExternalUserId"])&&exact(t.request,["jsonrpc","id","method","params"])&&exact(t.command,["context","name","params"])&&exact(n,["runtimeRunId","parts","conversationId","platformAgentId","taskId","taskRequestMessageId","replyMessageId","inputFingerprint","runtimeLease",...["mentions","mode","modelOverrideId"].filter(e=>void 0!==n[e])])&&object(o)&&exact(o,["runtimeEpoch","leaseId","journalStoreId","journalGeneration"])&&2===t.schemaVersion&&"cloud"===t.authorityRealm&&"session/prompt"===t.method&&t.request.method===t.method&&"2.0"===t.request.jsonrpc&&("string"==typeof t.request.id||"number"==typeof t.request.id)&&"session.prompt"===t.command.name&&isCloudRuntimeSubject(t.cloudSubject)&&isCloudRuntimeSubject(a.cloudSubject)&&semanticEqual(t.cloudSubject,a.cloudSubject)&&t.cloudSubject.instanceId===e.lease.instanceId&&t.instanceId===e.lease.instanceId&&t.runtimeHandlerIdentity===e.lease.handlerIdentity&&t.leaseId===e.lease.leaseId&&decimal(t.dispatchEpoch)&&decimal(o.runtimeEpoch)&&decimal(o.journalGeneration)&&o.runtimeEpoch===e.lease.runtimeEpoch&&o.leaseId===e.lease.leaseId&&o.journalStoreId===e.lineage.journalStoreId&&o.journalGeneration===e.lineage.journalGeneration&&nonempty(t.callerExternalUserId)&&nonempty(t.requestMessageId)&&t.requestMessageId!==n.taskRequestMessageId&&n.replyMessageId!==n.taskRequestMessageId&&[n.conversationId,n.platformAgentId,n.taskRequestMessageId,n.replyMessageId].every(nonempty)&&digest(n.inputFingerprint)&&n.taskId===t.operationId&&n.runtimeRunId===t.operationId&&"string"==typeof n.taskId&&/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(n.taskId)&&Array.isArray(n.parts)&&(void 0===n.mode||"string"==typeof n.mode)&&(void 0===n.modelOverrideId||"string"==typeof n.modelOverrideId)&&(void 0===n.mentions||Array.isArray(n.mentions))&&"conversation"===r.scope&&r.operationId===t.operationId&&r.dispatchEpoch===t.dispatchEpoch&&r.runtimeInstanceUid===t.instanceId&&r.paramsHash===t.paramsHash&&r.idempotencyKeyHash===t.idempotencyKeyHash&&r.claimDeadline===t.claimDeadlineAt&&r.executionDeadline===t.executionDeadlineAt&&decimal(r.historyGeneration)&&object(r.conversation)&&r.conversation.runtimeConversationUid===n.conversationId&&r.conversation.runtimeSessionKey===n.conversationId&&[t.requestHash,t.paramsHash,t.commandHash,t.callerIntentHash,t.idempotencyFingerprint,t.idempotencyKeyHash,t.executionGrantHash].every(digest)))return fail();const s={runtimeRunId:n.runtimeRunId,parts:n.parts,...void 0===n.mentions?{}:{mentions:n.mentions},...void 0===n.mode?{}:{mode:n.mode},...void 0===n.modelOverrideId?{}:{modelOverrideId:n.modelOverrideId}},i=e.now??Date.now();if(![t.createdAt,t.claimDeadlineAt,t.executionDeadlineAt].every(e=>"string"==typeof e&&Number.isFinite(Date.parse(e)))||Date.parse(t.createdAt)>Date.parse(t.claimDeadlineAt)||Date.parse(t.claimDeadlineAt)>Date.parse(t.executionDeadlineAt)||!e.allowExpiredReadOnly&&Date.parse(t.claimDeadlineAt)<=i||!e.allowExpiredReadOnly&&Date.parse(t.executionDeadlineAt)<=i||!semanticEqual(s,t.command.params)||runtimeMessageHash(RUNTIME_HASH_DOMAINS.request,t.request)!==t.requestHash||runtimeMessageHash(RUNTIME_HASH_DOMAINS.params,{method:t.method,params:n})!==t.paramsHash||runtimeMessageHash(RUNTIME_HASH_DOMAINS.command,{command:t.command})!==t.commandHash||runtimeMessageHash(RUNTIME_HASH_DOMAINS.cloudCallerIntent,runtimeCloudCallerIntentPayload(t.cloudSubject,"session/prompt",n,t.callerExternalUserId))!==t.callerIntentHash||runtimeMessageHash(RUNTIME_HASH_DOMAINS.cloudIdempotencyFingerprint,runtimeCloudIdempotencyFingerprintPayload(t.cloudSubject,"session/prompt",t.callerIntentHash))!==t.idempotencyFingerprint||e.decoded?.compactHash!==t.executionGrantHash)return fail();const d=Math.floor(i/1e3);if(!exact(a,["iss","aud","purpose","sub","jti","iat","exp","authorityRealm","cloudSubject","operationId","requestMessageId","instanceId","leaseId","handlerIdentity","dispatchEpoch","requestHash","paramsHash","commandHash","idempotencyKeyHash","executionMode","method","command","scope","callerExternalUserId","platformAgentId","runtimeAgentUid","platformConversationId","historyGeneration"])||"beeos-cloud-gateway"!==a.iss||"beeos-cloud-runtime-command"!==a.aud||"cloud-runtime-execution-grant"!==a.purpose||"cloud"!==a.authorityRealm||"start"!==a.executionMode||"conversation"!==a.scope||!nonempty(a.jti)||!nonempty(a.runtimeAgentUid)||!Number.isSafeInteger(a.iat)||!Number.isSafeInteger(a.exp)||a.iat>d||!e.allowExpiredReadOnly&&a.exp<=d||a.exp<=a.iat||a.exp-a.iat>60||a.sub!==e.lease.handlerIdentity||a.handlerIdentity!==e.lease.handlerIdentity||a.platformAgentId!==n.platformAgentId||a.platformConversationId!==n.conversationId||a.historyGeneration!==r.historyGeneration||!semanticEqual(a.command,t.command)||!semanticEqual(a.cloudSubject,t.cloudSubject)||["operationId","requestMessageId","instanceId","leaseId","dispatchEpoch","requestHash","paramsHash","commandHash","idempotencyKeyHash","callerExternalUserId","method"].some(e=>a[e]!==t[e]))return fail();const m=structuredClone(t),c={historyGeneration:r.historyGeneration,runtimeAgentUid:a.runtimeAgentUid,request:m,params:m.request.params,command:m.command};return verifiedPrompts.set(c,structuredClone(c)),c}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function prepareNativePromptInput(e){const t=[],i=[];for(const[r,n]of e.entries()){if("text"===n.type){if("string"!=typeof n.text||hasUnexpectedKey(n,["type","text"]))throw new TypeError("native text part unsupported or invalid");t.push(n.text);continue}if(!["image","audio","file","resource","resource_link"].includes(n.type)||void 0!==n.mimeType&&"string"!=typeof n.mimeType||"resource_link"!==n.type&&void 0!==n.fileName&&"string"!=typeof n.fileName||"resource_link"===n.type&&(void 0!==n.name&&"string"!=typeof n.name||void 0!==n.title&&"string"!=typeof n.title||void 0!==n.sizeBytes&&("string"!=typeof n.sizeBytes||!/^(0|[1-9][0-9]*)$/.test(n.sizeBytes))))throw new TypeError("native file part unsupported or invalid");const e="resource_link"===n.type?n.resourceRef:n.blobRef;if("string"!=typeof e||!/^beeos-file:\/\/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(e))throw new TypeError("native input part unsupported: canonical Cloud file reference required");i.push({partIndex:r,fileId:e.slice(13)})}return{message:t.join("\n"),files:i}}function hasUnexpectedKey(e,t){return Object.keys(e).some(e=>!t.includes(e))}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function nativeSessionNewSyncRequest(n){const e=nonEmpty(n.operationId);if(!e)throw new Error("native session/new sync requires a retained operationId");const s=nonEmpty(n.runtimeSessionId);if(!s)throw new Error("native session/new sync requires a runtimeSessionId");const o=nonEmpty(n.runtimeSessionKey),t=nonEmpty(n.title);return{schemaVersion:1,operationId:e,runtimeSessionId:s,...o?{runtimeSessionKey:o}:{},...t?{title:t}:{}}}export function assertCanonicalConversationSyncResponse(n){if(!n||"string"!=typeof n.id||0===n.id.length)throw new Error("native session/new sync response is missing a canonical conversation id");return n}export class NativeSessionNewBridge{options;constructor(n){this.options=n}async sync(n){const e=nativeSessionNewSyncRequest(n);this.options.logger?.info?.(`[native-cloud-chat] session/new sync operationId=${e.operationId} runtimeSessionId=${e.runtimeSessionId}`);return{conversation:assertCanonicalConversationSyncResponse(await this.options.client.syncConversation(e))}}}export async function syncNativeSessionNew(n,e){const s=nativeSessionNewSyncRequest(e);return assertCanonicalConversationSyncResponse(await n.syncConversation(s))}export function nativeSessionNewConversationCreator(n,e){const s=new NativeSessionNewBridge({client:n,...e?{logger:e}:{}});return{create:async n=>({conversationId:(await s.sync({operationId:n.operationId,runtimeSessionId:n.runtimeSessionId,runtimeSessionKey:n.runtimeSessionKey,...n.title?{title:n.title}:{}})).conversation.id})}}function nonEmpty(n){return"string"==typeof n&&n.length>0?n:void 0}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{AROUTER_PROVIDER_ID}from"../media/arouter-config.js";let snapshot;export function setOpenClawConfigSnapshot(t){snapshot=t}function listedModelIds(t){if(!t||!Array.isArray(t.models))return[];const o=[];for(const e of t.models){if("string"==typeof e){const t=e.trim();t&&o.push(t);continue}if(e&&"string"==typeof e.id){const t=e.id.trim();t&&o.push(t)}}return o}function primaryProvider(t){const o=t?.agents?.defaults?.model?.primary;if("string"!=typeof o)return;const e=o.indexOf("/");return e>0?o.slice(0,e):void 0}export function createSessionModelRefs(t=snapshot){const o=t?.models?.providers??{},e=Object.keys(o).filter(t=>null!=o[t]),n=new Map;for(const t of e)for(const e of listedModelIds(o[t]))n.set(e,n.has(e)?void 0:t);const r=primaryProvider(t),s=r&&e.includes(r)?r:1===e.length?e[0]:AROUTER_PROVIDER_ID,i=e.includes(AROUTER_PROVIDER_ID)?e:[...e,AROUTER_PROVIDER_ID],f=t=>i.find(o=>t.startsWith(`${o}/`));return{toOpenClaw(t){return f(t)?t:`${o=t,n.get(o)??s}/${t}`;var o},toPlatform(t){const o=f(t);return o?t.slice(o.length+1):t}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{enableDeepseekReasoningStream}from"./deepseek-reasoning-stream.js";const DEFAULT_ORIGINATING_CHANNEL="beeos-claw",DEFAULT_ORIGINATING_TARGET="main",DEFAULT_ORIGINATING_ACCOUNT_ID="main",isRecord=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),assertKnownReplyProtocol=e=>{if("acp"!==e&&"im"!==e)throw new Error(`unsupported reply route protocol=${e}`)},normalizeMediaUrls=e=>{if(!Array.isArray(e))return;const o=e.filter(e=>"string"==typeof e&&e.length>0);return o.length>0?o:void 0};export const hasRuntimeReplyApi=e=>"function"==typeof e?.channel?.reply?.dispatchReplyFromConfig;export const buildFinalizedMsgContext=(e,o)=>{assertKnownReplyProtocol(o.protocol);const r=o.originatingChannel??"beeos-claw",t=o.originatingTo??"main",n=o.accountId??"main",i=normalizeMediaUrls(e.attachments);return{Body:e.message,BodyForAgent:e.agentMessage,From:`${r}:${t}`,To:t,SessionKey:o.sessionId,Surface:r,Provider:r,OriginatingChannel:r,OriginatingTo:t,AccountId:n,CommandAuthorized:!0,...i?{MediaUrls:i}:{}}};export const resolveReplySinkForRoute=(e,o)=>{assertKnownReplyProtocol(e.protocol);const r=o[e.protocol];if(!r)throw new Error(`runtime reply sink unavailable protocol=${e.protocol} requestId=${e.requestId}`);return r};const resolveRuntimeDispatchConfig=(e,o)=>{try{const o=e.config?.loadConfig?.();if(isRecord(o))return o}catch{}return o};export const dispatchRuntimeReplyWithRoute=async e=>{const o=e.runtime.channel?.reply?.dispatchReplyFromConfig;if("function"!=typeof o)throw new Error(`runtime reply API unavailable protocol=${e.replyRoute.protocol} requestId=${e.replyRoute.requestId}`);const r=resolveReplySinkForRoute(e.replyRoute,e.replySinks),t=enableDeepseekReasoningStream(resolveRuntimeDispatchConfig(e.runtime,e.pluginConfig)),n=o({ctx:buildFinalizedMsgContext(e.preparedPrompt,e.replyRoute),cfg:t,dispatcher:r.dispatcher,replyOptions:r.replyOptions});return e.onDispatchInvoked?.(),n};
|
|
1
|
+
import{enableDeepseekReasoningStream}from"./deepseek-reasoning-stream.js";const DEFAULT_ORIGINATING_CHANNEL="beeos-claw",DEFAULT_ORIGINATING_TARGET="main",DEFAULT_ORIGINATING_ACCOUNT_ID="main",isRecord=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),assertKnownReplyProtocol=e=>{if("acp"!==e&&"im"!==e)throw new Error(`unsupported reply route protocol=${e}`)},normalizeMediaUrls=e=>{if(!Array.isArray(e))return;const o=e.filter(e=>"string"==typeof e&&e.length>0);return o.length>0?o:void 0};export const hasRuntimeReplyApi=e=>"function"==typeof e?.channel?.reply?.dispatchReplyFromConfig;export const buildFinalizedMsgContext=(e,o)=>{assertKnownReplyProtocol(o.protocol);const r=o.originatingChannel??"beeos-claw",t=o.originatingTo??"main",n=o.accountId??"main",i=normalizeMediaUrls(e.attachments);return{Body:e.message,BodyForAgent:e.agentMessage,From:`${r}:${t}`,To:t,SessionKey:o.sessionId,Surface:r,Provider:r,OriginatingChannel:r,OriginatingTo:t,AccountId:n,CommandAuthorized:!0,...i?{MediaUrls:i}:{},...e.mediaPaths?.length?{MediaPaths:e.mediaPaths,MediaTypes:e.mediaTypes}:{}}};export const resolveReplySinkForRoute=(e,o)=>{assertKnownReplyProtocol(e.protocol);const r=o[e.protocol];if(!r)throw new Error(`runtime reply sink unavailable protocol=${e.protocol} requestId=${e.requestId}`);return r};const resolveRuntimeDispatchConfig=(e,o)=>{try{const o=e.config?.loadConfig?.();if(isRecord(o))return o}catch{}return o};export const dispatchRuntimeReplyWithRoute=async e=>{const o=e.runtime.channel?.reply?.dispatchReplyFromConfig;if("function"!=typeof o)throw new Error(`runtime reply API unavailable protocol=${e.replyRoute.protocol} requestId=${e.replyRoute.requestId}`);const r=resolveReplySinkForRoute(e.replyRoute,e.replySinks),t=enableDeepseekReasoningStream(resolveRuntimeDispatchConfig(e.runtime,e.pluginConfig)),n=o({ctx:buildFinalizedMsgContext(e.preparedPrompt,e.replyRoute),cfg:t,dispatcher:r.dispatcher,replyOptions:r.replyOptions});return e.onDispatchInvoked?.(n),n};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const RUNTIME_ERROR_PART_KIND="runtime_error";const RUNTIME_ERROR_CODES=["insufficient_credits"];export function createRuntimeErrorPart(r){return{type:"custom",kind:"runtime_error",data:{code:r}}}export function parseRuntimeErrorPart(r){if(!r||"object"!=typeof r||Array.isArray(r))return;const t=r;if("custom"!==t.type||"runtime_error"!==t.kind)return;const e=t.data;if(!e||"object"!=typeof e||Array.isArray(e))return;const n=e.code;return"string"==typeof n&&RUNTIME_ERROR_CODES.includes(n)?createRuntimeErrorPart(n):void 0}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{RUNTIME_INVOCATION_RECOVERY_CLASSES,RUNTIME_METHOD_PARITY_MANIFEST}from"@beeos-ai/beeos-types/runtime";export const RUNTIME_LOCAL_PARITY_MATRIX=Object.freeze(RUNTIME_METHOD_PARITY_MANIFEST.filter(e=>"request"===e.acpMessage&&e.serviceAllowed&&e.canonicalCommand&&e.acpMethod in RUNTIME_INVOCATION_RECOVERY_CLASSES&&("methods"===e.serviceRoute||"conversation-api"===e.serviceRoute)).map(e=>{const r=e.acpMethod,t="query"===e.recoveryClass?[]:["runtime_effect_committed"];return Object.freeze({method:r,acp:Object.freeze({params:e.acpParamsType,result:e.acpResultType,errors:Object.freeze([...e.acpErrors])}),service:Object.freeze({method:e.serviceMethod,command:e.canonicalCommand,events:Object.freeze(["runtime_operation_started","runtime_operation_progress*",...t,"runtime_rpc_response"]),finalResult:`CanonicalCommandResult<${JSON.stringify(e.canonicalCommand)}>`,errors:Object.freeze([...e.serviceErrors])}),fixture:Object.freeze({status:"ready",kind:"wire-fixture",acpEvidence:"src/acp-gateway/bridge-core shared-Core request/result/error fixtures",serviceEvidence:"src/runtime/ms-runtime-rpc-adapter-parity.test.ts canonical/events/final fixtures"}),activation:Object.freeze({status:"ready",requirements:Object.freeze([])})})}));export const RUNTIME_LOCAL_FIXTURE_READY_METHODS=Object.freeze(new Set(RUNTIME_LOCAL_PARITY_MATRIX.filter(e=>"ready"===e.fixture.status).map(e=>e.method)));
|
|
1
|
+
import{RUNTIME_INVOCATION_RECOVERY_CLASSES,RUNTIME_METHOD_PARITY_MANIFEST}from"@beeos-ai/beeos-types/runtime";export const RUNTIME_LOCAL_PARITY_MATRIX=Object.freeze(RUNTIME_METHOD_PARITY_MANIFEST.filter(e=>"request"===e.acpMessage&&e.serviceAllowed&&e.canonicalCommand&&e.acpMethod in RUNTIME_INVOCATION_RECOVERY_CLASSES&&("methods"===e.serviceRoute||"conversation-api"===e.serviceRoute)).map(e=>{const r=e.acpMethod,t="query"===e.recoveryClass||"session/new"===r?[]:["runtime_effect_committed"];return Object.freeze({method:r,acp:Object.freeze({params:e.acpParamsType,result:e.acpResultType,errors:Object.freeze([...e.acpErrors])}),service:Object.freeze({method:e.serviceMethod,command:e.canonicalCommand,events:Object.freeze(["runtime_operation_started","runtime_operation_progress*",...t,"runtime_rpc_response"]),finalResult:`CanonicalCommandResult<${JSON.stringify(e.canonicalCommand)}>`,errors:Object.freeze([...e.serviceErrors])}),fixture:Object.freeze({status:"ready",kind:"wire-fixture",acpEvidence:"src/acp-gateway/bridge-core shared-Core request/result/error fixtures",serviceEvidence:"session/new"===r?"src/runtime/native-session-new-go-wire.test.ts Go/MS HTTP/RS256/Core/sync/final fixture":"src/runtime/ms-runtime-rpc-adapter-parity.test.ts canonical/events/final fixtures"}),activation:Object.freeze({status:"ready",requirements:Object.freeze([])})})}));export const RUNTIME_LOCAL_FIXTURE_READY_METHODS=Object.freeze(new Set(RUNTIME_LOCAL_PARITY_MATRIX.filter(e=>"ready"===e.fixture.status).map(e=>e.method)));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash}from"node:crypto";import{CONVERSATION_RUNTIME_CANONICAL_COMMAND_NAMES,RUNTIME_HASH_DOMAINS,RUNTIME_INVOCATION_RECOVERY_CLASSES,RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION,SERVICE_CANONICAL_COMMAND_NAMES,canonicalizeJcs,runtimeIdempotencyFingerprintPayload,runtimeHashPreimage,validateRuntimeRpcRequestResourceBindings}from"@beeos-ai/beeos-types/runtime";import{sessionSetModelMappingMatches}from"./session-set-model-mapping.js";export const RUNTIME_MESSAGE_TYPES=Object.freeze({request:"runtime_rpc_request",started:"runtime_operation_started",progress:"runtime_operation_progress",effectCommitted:"runtime_effect_committed",final:"runtime_rpc_response",projectionPending:"runtime_projection_pending",projectionSynced:"runtime_projection_synced",projectionBlocked:"runtime_projection_blocked",cancel:"runtime_operation_cancel_requested"});const methods=new Set(Object.keys(RUNTIME_INVOCATION_RECOVERY_CLASSES)),commandNames={...SERVICE_CANONICAL_COMMAND_NAMES,...CONVERSATION_RUNTIME_CANONICAL_COMMAND_NAMES},sha=/^[0-9a-f]{64}$/,decimal=/^(0|[1-9][0-9]*)$/;export function validateRuntimeRequestEnvelope(e){if(!record(e)||e.type!==RUNTIME_MESSAGE_TYPES.request||!record(e.payload))return{ok:!1,reason:"delivery is not a runtime request"};const t=e,n=t.payload;if(!exactKeys(t,["message_id","offset","channel_id","type","payload","publisher_id","idempotency_key","created_at","state",...void 0===t.in_reply_to?[]:["in_reply_to"]])||void 0!==t.in_reply_to||"completed"!==t.state||!nonempty(t.message_id)||!nonempty(t.channel_id)||!Number.isInteger(t.offset)||t.offset<1||!nonempty(t.publisher_id)||!nonempty(t.idempotency_key))return{ok:!1,reason:"invalid persisted envelope"};const r=void 0!==n.resourceBindingContractRevision,a=void 0!==n.resourceBindings;if(!exactKeys(n,["schemaVersion","operationId","requestMessageId","requestHash","paramsHash","commandHash","idempotencyKeyHash","idempotencyFingerprint","callerIntentHash","callerUserId","callerIdentityId","instanceId","runtimeHandlerIdentity","dispatchEpoch","method","request","command","executionGrantHash","claimDeadlineAt","executionDeadlineAt","createdAt",...r||a?["resourceBindingContractRevision","resourceBindings"]:[]]))return{ok:!1,reason:"request payload fields do not match v1.3"};if(r!==a||r&&n.resourceBindingContractRevision!==RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION||a&&!Array.isArray(n.resourceBindings))return{ok:!1,reason:"resource binding carrier is invalid"};if(!(1===n.schemaVersion&&methods.has(n.method)&&decimal.test(n.dispatchEpoch)&&[n.operationId,n.requestMessageId,n.callerUserId,n.callerIdentityId,n.instanceId,n.runtimeHandlerIdentity].every(nonempty)&&[n.requestHash,n.paramsHash,n.commandHash,n.idempotencyKeyHash,n.idempotencyFingerprint,n.callerIntentHash,n.executionGrantHash].every(e=>"string"==typeof e&&sha.test(e))&&record(n.request)&&record(n.command)&&"2.0"===n.request.jsonrpc&&n.request.method===n.method&&n.command.name===commandNames[n.method]))return{ok:!1,reason:"invalid request union"};if(!sessionSetModelMappingMatches(n.request,n.command))return{ok:!1,reason:"request command mapping mismatch"};if(t.channel_id!==n.operationId||t.message_id!==n.requestMessageId||n.command.context?.operationId!==n.operationId||n.command.context?.runtimeInstanceUid!==n.instanceId||n.command.context?.dispatchEpoch!==n.dispatchEpoch||n.command.context?.paramsHash!==n.paramsHash||n.command.context?.idempotencyKeyHash!==n.idempotencyKeyHash||n.command.context?.claimDeadline!==n.claimDeadlineAt||n.command.context?.executionDeadline!==n.executionDeadlineAt)return{ok:!1,reason:"request correlation mismatch"};try{const e={callerUserId:n.callerUserId,instanceId:n.instanceId,method:n.method,params:n.request.params};if(digest(RUNTIME_HASH_DOMAINS.request,n.request)!==n.requestHash||digest(RUNTIME_HASH_DOMAINS.params,{method:n.method,params:n.request.params})!==n.paramsHash||digest(RUNTIME_HASH_DOMAINS.command,{command:n.command})!==n.commandHash||digest(RUNTIME_HASH_DOMAINS.callerIntent,e)!==n.callerIntentHash||digest(RUNTIME_HASH_DOMAINS.idempotencyFingerprint,runtimeIdempotencyFingerprintPayload(n.callerUserId,n.instanceId,n.method,n.callerIntentHash))!==n.idempotencyFingerprint)return{ok:!1,reason:"canonical hash mismatch"}}catch{return{ok:!1,reason:"canonical hash mismatch"}}if(![n.claimDeadlineAt,n.executionDeadlineAt,n.createdAt].every(e=>"string"==typeof e&&Number.isFinite(Date.parse(e))))return{ok:!1,reason:"invalid request timestamp"};if(r){let e;try{e=validateRuntimeRpcRequestResourceBindings({type:"runtime_rpc_request",operationId:n.operationId,requestMessageId:n.requestMessageId,payload:n},Math.floor(Date.now()/1e3))}catch{return{ok:!1,reason:"resource binding validation failed"}}if(e.length)return{ok:!1,reason:"resource binding validation failed"}}return{ok:!0,envelope:t}}export function validateRuntimeCancelEnvelope(e){if(!record(e)||e.type!==RUNTIME_MESSAGE_TYPES.cancel||!record(e.payload))return{ok:!1,reason:"delivery is not a runtime cancel"};const t=e,n=t.payload;return exactKeys(n,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","eventId","requestedBy",...void 0===n.reason?[]:["reason"]])&&exactKeys(t,["message_id","offset","channel_id","type","payload","publisher_id","idempotency_key","created_at","state"])&&"completed"===t.state&&nonempty(t.message_id)&&Number.isInteger(t.offset)&&!(t.offset<1)&&nonempty(t.publisher_id)&&nonempty(t.idempotency_key)&&1===n.schemaVersion&&methods.has(n.method)&&decimal.test(n.dispatchEpoch)&&sha.test(n.requestHash)&&t.channel_id===n.operationId&&void 0===t.in_reply_to&&nonempty(n.eventId)&&nonempty(n.requestedBy)&&(void 0===n.reason||"string"==typeof n.reason)?{ok:!0,envelope:t}:{ok:!1,reason:"invalid cancel correlation"}}export function runtimeMessageBase(e){return{schemaVersion:1,operationId:e.operationId,requestMessageId:e.requestMessageId,requestHash:e.requestHash,dispatchEpoch:e.dispatchEpoch,method:e.method}}export function runtimeMessageHash(e,t){return digest(e,t)}function digest(e,t){return createHash("sha256").update(runtimeHashPreimage(e,t)).digest("hex")}function record(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}function nonempty(e){return"string"==typeof e&&e.length>0}function exactKeys(e,t){const n=Object.keys(e).sort(),r=[...t].sort();return n.length===r.length&&n.every((e,t)=>e===r[t])}export function semanticEqual(e,t){return canonicalizeJcs(e)===canonicalizeJcs(t)}
|
|
1
|
+
import{createHash}from"node:crypto";import{CONVERSATION_RUNTIME_CANONICAL_COMMAND_NAMES,RUNTIME_HASH_DOMAINS,RUNTIME_INVOCATION_RECOVERY_CLASSES,RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION,SERVICE_CANONICAL_COMMAND_NAMES,canonicalizeJcs,isCloudRuntimeMessageRequest,runtimeIdempotencyFingerprintPayload,runtimeHashPreimage,validateRuntimeRpcRequestResourceBindings}from"@beeos-ai/beeos-types/runtime";import{sessionSetModelMappingMatches}from"./session-set-model-mapping.js";export const RUNTIME_MESSAGE_TYPES=Object.freeze({request:"runtime_rpc_request",started:"runtime_operation_started",progress:"runtime_operation_progress",effectCommitted:"runtime_effect_committed",final:"runtime_rpc_response",projectionPending:"runtime_projection_pending",projectionSynced:"runtime_projection_synced",projectionBlocked:"runtime_projection_blocked",cancel:"runtime_operation_cancel_requested"});const methods=new Set(Object.keys(RUNTIME_INVOCATION_RECOVERY_CLASSES)),commandNames={...SERVICE_CANONICAL_COMMAND_NAMES,...CONVERSATION_RUNTIME_CANONICAL_COMMAND_NAMES},sha=/^[0-9a-f]{64}$/,decimal=/^(0|[1-9][0-9]*)$/;export function validateRuntimeRequestEnvelope(e){if(!record(e)||e.type!==RUNTIME_MESSAGE_TYPES.request||!record(e.payload))return{ok:!1,reason:"delivery is not a runtime request"};const t=e,n=t.payload;if(!exactKeys(t,["message_id","offset","channel_id","type","payload","publisher_id","idempotency_key","created_at","state",...void 0===t.in_reply_to?[]:["in_reply_to"]])||void 0!==t.in_reply_to||"completed"!==t.state||!nonempty(t.message_id)||!nonempty(t.channel_id)||!Number.isInteger(t.offset)||t.offset<1||!nonempty(t.publisher_id)||!nonempty(t.idempotency_key))return{ok:!1,reason:"invalid persisted envelope"};if(2===n.schemaVersion)return isCloudRuntimeMessageRequest(n,digest)?t.channel_id!==n.operationId||t.message_id!==n.requestMessageId?{ok:!1,reason:"request correlation mismatch"}:{ok:!0,envelope:t}:{ok:!1,reason:"invalid Cloud runtime request"};const r=void 0!==n.resourceBindingContractRevision,a=void 0!==n.resourceBindings;if(!exactKeys(n,["schemaVersion","operationId","requestMessageId","requestHash","paramsHash","commandHash","idempotencyKeyHash","idempotencyFingerprint","callerIntentHash","callerUserId","callerIdentityId","instanceId","runtimeHandlerIdentity","dispatchEpoch","method","request","command","executionGrantHash","claimDeadlineAt","executionDeadlineAt","createdAt",...r||a?["resourceBindingContractRevision","resourceBindings"]:[]]))return{ok:!1,reason:"request payload fields do not match v1.3"};if(r!==a||r&&n.resourceBindingContractRevision!==RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION||a&&!Array.isArray(n.resourceBindings))return{ok:!1,reason:"resource binding carrier is invalid"};if(!(1===n.schemaVersion&&methods.has(n.method)&&decimal.test(n.dispatchEpoch)&&[n.operationId,n.requestMessageId,n.callerUserId,n.callerIdentityId,n.instanceId,n.runtimeHandlerIdentity].every(nonempty)&&[n.requestHash,n.paramsHash,n.commandHash,n.idempotencyKeyHash,n.idempotencyFingerprint,n.callerIntentHash,n.executionGrantHash].every(e=>"string"==typeof e&&sha.test(e))&&record(n.request)&&record(n.command)&&"2.0"===n.request.jsonrpc&&n.request.method===n.method&&n.command.name===commandNames[n.method]))return{ok:!1,reason:"invalid request union"};if(!sessionSetModelMappingMatches(n.request,n.command))return{ok:!1,reason:"request command mapping mismatch"};if(t.channel_id!==n.operationId||t.message_id!==n.requestMessageId||n.command.context?.operationId!==n.operationId||n.command.context?.runtimeInstanceUid!==n.instanceId||n.command.context?.dispatchEpoch!==n.dispatchEpoch||n.command.context?.paramsHash!==n.paramsHash||n.command.context?.idempotencyKeyHash!==n.idempotencyKeyHash||n.command.context?.claimDeadline!==n.claimDeadlineAt||n.command.context?.executionDeadline!==n.executionDeadlineAt)return{ok:!1,reason:"request correlation mismatch"};try{const e={callerUserId:n.callerUserId,instanceId:n.instanceId,method:n.method,params:n.request.params};if(digest(RUNTIME_HASH_DOMAINS.request,n.request)!==n.requestHash||digest(RUNTIME_HASH_DOMAINS.params,{method:n.method,params:n.request.params})!==n.paramsHash||digest(RUNTIME_HASH_DOMAINS.command,{command:n.command})!==n.commandHash||digest(RUNTIME_HASH_DOMAINS.callerIntent,e)!==n.callerIntentHash||digest(RUNTIME_HASH_DOMAINS.idempotencyFingerprint,runtimeIdempotencyFingerprintPayload(n.callerUserId,n.instanceId,n.method,n.callerIntentHash))!==n.idempotencyFingerprint)return{ok:!1,reason:"canonical hash mismatch"}}catch{return{ok:!1,reason:"canonical hash mismatch"}}if(![n.claimDeadlineAt,n.executionDeadlineAt,n.createdAt].every(e=>"string"==typeof e&&Number.isFinite(Date.parse(e))))return{ok:!1,reason:"invalid request timestamp"};if(r){let e;try{e=validateRuntimeRpcRequestResourceBindings({type:"runtime_rpc_request",operationId:n.operationId,requestMessageId:n.requestMessageId,payload:n},Math.floor(Date.now()/1e3))}catch{return{ok:!1,reason:"resource binding validation failed"}}if(e.length)return{ok:!1,reason:"resource binding validation failed"}}return{ok:!0,envelope:t}}export function validateRuntimeCancelEnvelope(e){if(!record(e)||e.type!==RUNTIME_MESSAGE_TYPES.cancel||!record(e.payload))return{ok:!1,reason:"delivery is not a runtime cancel"};const t=e,n=t.payload;return exactKeys(n,["schemaVersion","operationId","requestMessageId","requestHash","dispatchEpoch","method","eventId","requestedBy",...void 0===n.reason?[]:["reason"]])&&exactKeys(t,["message_id","offset","channel_id","type","payload","publisher_id","idempotency_key","created_at","state"])&&"completed"===t.state&&nonempty(t.message_id)&&Number.isInteger(t.offset)&&!(t.offset<1)&&nonempty(t.publisher_id)&&nonempty(t.idempotency_key)&&1===n.schemaVersion&&methods.has(n.method)&&decimal.test(n.dispatchEpoch)&&sha.test(n.requestHash)&&t.channel_id===n.operationId&&void 0===t.in_reply_to&&nonempty(n.eventId)&&nonempty(n.requestedBy)&&(void 0===n.reason||"string"==typeof n.reason)?{ok:!0,envelope:t}:{ok:!1,reason:"invalid cancel correlation"}}export function runtimeMessageBase(e){return{schemaVersion:1,operationId:e.operationId,requestMessageId:e.requestMessageId,requestHash:e.requestHash,dispatchEpoch:e.dispatchEpoch,method:e.method}}export function runtimeMessageHash(e,t){return digest(e,t)}function digest(e,t){return createHash("sha256").update(runtimeHashPreimage(e,t)).digest("hex")}function record(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}function nonempty(e){return"string"==typeof e&&e.length>0}function exactKeys(e,t){const n=Object.keys(e).sort(),r=[...t].sort();return n.length===r.length&&n.every((e,t)=>e===r[t])}export function semanticEqual(e,t){return canonicalizeJcs(e)===canonicalizeJcs(t)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash}from"node:crypto";import{
|
|
1
|
+
import{createHash}from"node:crypto";import{hashRuntimeResourceRedemptionPayload,normalizeRuntimeResourceRedemptionHashPayload,validateRuntimeMcpResourceRedemptionCompletion,validateRuntimeSkillResourceRedemptionCompletion}from"@beeos-ai/beeos-types/runtime";export class RuntimeResourceResolutionError extends Error{kind;code;diagnostic;constructor(e,t,i,r){super(r?`${t} [${r}]`:t),this.kind=e,this.code=i,this.diagnostic=r,this.name="RuntimeResourceResolutionError"}}export class HttpRuntimeOperationResourceResolver{options;attempts=new Map;byRef;mcp;skill;constructor(e){this.options=e;const t=e.bindings.map(e=>[e.resourceRef,Object.freeze({...e})]);if(new Set(t.map(([e])=>e)).size!==t.length)throw new Error("duplicate resource binding");this.byRef=new Map(t)}async readContent(){throw new Error("Service inline content is forbidden; use a trusted artifact reference")}async resolveMcpDefinition(e){this.mcp||(this.mcp=this.redeemMcp(e).catch(e=>{throw this.mcp=void 0,e}));const t=await this.mcp;if(!sameMcpDescriptor(t.descriptor,e))throw new Error("MCP resource descriptor mismatch");return t.config}async resolveMcpCredential(e){this.mcp||(this.mcp=this.redeemMcp(e).catch(e=>{throw this.mcp=void 0,e}));const t=await this.mcp;if(!sameMcpDescriptor(t.descriptor,e))throw new Error("MCP resource descriptor mismatch");return t.credential}async readVerifiedArtifact(e){this.skill||(this.skill=this.redeemSkill(e).catch(e=>{throw this.skill=void 0,e}));const t=await this.skill;if(!sameArtifactDescriptor(t.descriptor,e))throw new Error("skill resource descriptor mismatch");return t.parsed}async redeemMcp(e){const t=this.bindingFor("mcp",e.definitionRef);if(t.version!==e.version||t.sha256!==e.sha256)throw resolution("MCP descriptor does not match the immutable authority binding","descriptor_binding_mismatch");const{request:i,reservation:r}=this.requestFor(t),s=await this.redeem(t,i);let o;try{o=await s.json()}catch{throw integrity("MCP authority response is invalid","response_not_json")}const n=validateRuntimeMcpResourceRedemptionCompletion({request:i,binding:t,reservation:r,expectedDisposition:o.disposition,result:o,sha256Utf8:sha256Utf8});if(!n.valid)throw integrity("MCP resource integrity failed",`violations=${n.violations.join(",")}`);if(!isPlainObject(o.resource.config))throw integrity("MCP authority payload must contain public object config","config_not_object");const a=void 0===o.resource.credential?void 0:credentialMaterial(o.resource.credential);return{descriptor:e,config:Object.freeze({...o.resource.config}),credential:a}}async redeemSkill(e){const t=this.bindingFor("skill",e.artifactRef);if(t.version!==e.version||t.sha256!==e.sha256||t.sizeBytes!==e.sizeBytes)throw resolution("skill descriptor does not match the immutable authority binding","descriptor_binding_mismatch");const{request:i,reservation:r}=this.requestFor(t),s=await this.redeem(t,i),o=new Uint8Array(await s.arrayBuffer()),n=skillHeaders(s),a=validateRuntimeSkillResourceRedemptionCompletion({request:i,binding:t,reservation:r,expectedDisposition:n["X-BeeOS-Redemption-Disposition"],headers:n,chunks:[o],sha256Utf8:sha256Utf8,sha256Bytes:sha256Bytes});if(!a.valid)throw integrity("skill resource integrity failed",`violations=${a.violations.join(",")} bytes=${o.byteLength}`);return{descriptor:e,parsed:await this.options.parseSkillArtifact(o)}}bindingFor(e,t){const i=this.byRef.get(t);if(!i||i.kind!==e||i.operationId!==this.options.operationId||i.instanceId!==this.options.instanceId||i.requestMessageId!==this.options.requestMessageId||i.paramsHash!==this.options.paramsHash)throw resolution("resource authority binding mismatch",`kind=${e} ${i?i.kind!==e?"field=kind":i.operationId!==this.options.operationId?"field=operationId":i.instanceId!==this.options.instanceId?"field=instanceId":i.requestMessageId!==this.options.requestMessageId?"field=requestMessageId":"field=paramsHash":"resourceRef=unbound"}`);return i}requestFor(e){const t=this.options.getAuthorization(),i=this.attempts.get(e.resourceRef),r=i?.redemptionId??(this.options.redemptionId?this.options.redemptionId():stableRedemptionId(e)),s={redemptionId:r,operationId:this.options.operationId,requestMessageId:this.options.requestMessageId,kind:e.kind,resourceRef:e.resourceRef,paramsHash:this.options.paramsHash,executionGrant:t.executionGrant,runtimeLeaseCredential:t.runtimeLeaseCredential,fence:t.fence},o=normalizeRuntimeResourceRedemptionHashPayload(s,e);if(!o)throw resolution("resource redemption request does not match immutable binding","request_binding_mismatch");const n=hashRuntimeResourceRedemptionPayload(o,sha256Utf8);if(i&&i.requestHash!==n)throw resolution("resource redemption intent changed","redemption_intent_changed");return this.attempts.set(e.resourceRef,{redemptionId:r,requestHash:n}),{request:s,reservation:{state:"reserved",redemptionId:r,redemptionRequestHash:n}}}async redeem(e,t){let i;try{i=await this.options.gateway.runtime.redeemResource(e.operationId,e.kind,e.resourceRef,t,this.options.signal?{signal:this.options.signal}:void 0)}catch{throw transient("runtime resource authority is unavailable","fetch_rejected")}return i.ok||await throwRedemptionFailure(i,e.kind),i}}function skillHeaders(e){const t=t=>{const i=e.headers.get(t);if(!i)throw integrity(`skill authority response omitted ${t}`,`missing_header=${t}`);return i};return{"X-BeeOS-Redemption-Id":t("X-BeeOS-Redemption-Id"),"X-BeeOS-Redemption-Disposition":t("X-BeeOS-Redemption-Disposition"),"X-BeeOS-Artifact-Ref":t("X-BeeOS-Artifact-Ref"),"X-BeeOS-Artifact-Version":t("X-BeeOS-Artifact-Version"),"X-BeeOS-Artifact-SHA256":t("X-BeeOS-Artifact-SHA256"),"X-BeeOS-Artifact-Size":t("X-BeeOS-Artifact-Size")}}function sha256Utf8(e){return createHash("sha256").update(e).digest("hex")}function stableRedemptionId(e){return`redemption:${sha256Utf8(`${e.operationId}\n${e.requestMessageId}\n${e.kind}\n${e.resourceRef}`)}`}function sha256Bytes(e){const t=createHash("sha256");for(const i of e)t.update(i);return t.digest("hex")}function sameMcpDescriptor(e,t){return e.definitionRef===t.definitionRef&&e.version===t.version&&e.sha256===t.sha256}function sameArtifactDescriptor(e,t){return e.artifactRef===t.artifactRef&&e.version===t.version&&e.sha256===t.sha256&&e.sizeBytes===t.sizeBytes&&e.source===t.source}function isPlainObject(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)&&(Object.getPrototypeOf(e)===Object.prototype||null===Object.getPrototypeOf(e))}function credentialMaterial(e){if(!isPlainObject(e)||Object.keys(e).some(e=>"headers"!==e&&"env"!==e))throw integrity("MCP credential payload is invalid","credential_payload_invalid");const t=stringMap(e.headers,"MCP credential headers"),i=stringMap(e.env,"MCP credential environment");if(!t&&!i)throw integrity("MCP credential payload is empty","credential_payload_empty");return Object.freeze({...t?{headers:Object.freeze(t)}:{},...i?{env:Object.freeze(i)}:{}})}function stringMap(e,t){if(void 0!==e){if(!isPlainObject(e)||Object.entries(e).some(([e,t])=>!e||e.length>256||/[\u0000-\u001f\u007f]/.test(e)||"string"!=typeof t||t.length>16384))throw integrity(`${t} are invalid`,"credential_string_map_invalid");return{...e}}}async function throwRedemptionFailure(e,t){if(408===e.status||425===e.status||429===e.status||e.status>=500)throw transient(`runtime ${t} redemption is temporarily unavailable`,`http_status=${e.status}`);let i;try{i=await e.json()}catch{throw integrity(`runtime ${t} redemption error is invalid`,`http_status=${e.status} error_body=not_json`)}const r=redemptionError(i);if(!r)throw integrity(`runtime ${t} redemption error is invalid`,`http_status=${e.status} error_body=unrecognized_shape`);throw new RuntimeResourceResolutionError("resolution_rejected",`runtime ${t} redemption was rejected`,r.code,`http_status=${e.status} code=${r.code}`)}function redemptionError(e){if(!isPlainObject(e)||"string"!=typeof e.status||"string"!=typeof e.code)return;if("fenced"===e.status&&"FENCED"===e.code&&"string"==typeof e.activeRuntimeEpoch&&/^(0|[1-9][0-9]*)$/.test(e.activeRuntimeEpoch)&&exact(e,["status","code","activeRuntimeEpoch"]))return e;return[["expired","EXPIRED"],["resource_not_found","RESOURCE_NOT_FOUND"],["redemption_conflict","REDEMPTION_CONFLICT"],["resource_integrity_failed","RESOURCE_INTEGRITY_FAILED"],["unauthorized","UNAUTHORIZED"]].some(([t,i])=>e.status===t&&e.code===i&&exact(e,["status","code"]))?e:void 0}function exact(e,t){const i=Object.keys(e).sort(),r=[...t].sort();return i.length===r.length&&i.every((e,t)=>e===r[t])}function resolution(e,t){return new RuntimeResourceResolutionError("resolution_rejected",e,void 0,t)}function integrity(e,t){return new RuntimeResourceResolutionError("integrity_mismatch",e,void 0,t)}function transient(e,t){return new RuntimeResourceResolutionError("transient",e,"TRANSIENT",t)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash}from"node:crypto";import{readFileSync}from"node:fs";import{createRequire}from"node:module";import{canonicalizeJcs}from"@beeos-ai/beeos-types/runtime";export const EXPECTED_RUNTIME_PARITY_MANIFEST_DIGEST="
|
|
1
|
+
import{createHash}from"node:crypto";import{readFileSync}from"node:fs";import{createRequire}from"node:module";import{canonicalizeJcs}from"@beeos-ai/beeos-types/runtime";export const EXPECTED_RUNTIME_PARITY_MANIFEST_DIGEST="2e58dbc13b8bef2491b95f89920945cb905085828b2fa7a4d4f621624971b186";const require=createRequire(import.meta.url);export function computeRuntimeParityManifestDigest(){const e=require.resolve("@beeos-ai/beeos-types/contracts/runtime-method-manifest.v1.json"),t=JSON.parse(readFileSync(e,"utf8"));return createHash("sha256").update(canonicalizeJcs(t),"utf8").digest("hex")}export function verifiedRuntimeParityManifestDigest(){return requireExpectedRuntimeParityManifestDigest(computeRuntimeParityManifestDigest())}export function requireExpectedRuntimeParityManifestDigest(e){if(e!==EXPECTED_RUNTIME_PARITY_MANIFEST_DIGEST)throw new Error(`BeeOS Types parity manifest digest mismatch: expected ${EXPECTED_RUNTIME_PARITY_MANIFEST_DIGEST}, received ${e}`);return e}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const RUNTIME_MESSAGE_CHANNEL_REVISION="beeos.runtime-message-channel.v2.0.0";export const RUNTIME_MESSAGE_CHANNEL_RAW_SHA256="dd791ce5f49b7bee1dba21a71e7b2cfbf4db7d77cb787aab5f04c7f4b0e3101b";export const RUNTIME_MESSAGE_CHANNEL_SHA256="e950f1a86bf2bd8bf472603a91111c15b920fcac4c06fd8ac70e2c3f4c3a408f";export const RUNTIME_AUTHORITY_PORTS_REVISION="beeos.runtime-authority-ports.v2.0.0";export const RUNTIME_AUTHORITY_PORTS_RAW_SHA256="a2e9565ae617bcaeb4d837fe176a3602be041913d28a3f0a3a9ec2e3dae0d7b4";export const RUNTIME_AUTHORITY_PORTS_SHA256="3bd582f1f6babcdbe953a082faf813247c960f6bbf4c0f713e7fd92e27d163f5";export const RUNTIME_SESSION_CANCEL_REVISION="beeos.runtime-session-cancel.v1.0.0";export const RUNTIME_SESSION_CANCEL_SHA256="ad32581546f3a97d62df3a6785e3ec057e7dd888b31885f46cfb43d07c966d3e";export const RUNTIME_PARITY_MANIFEST_REVISION="beeos.runtime-parity.v1.1.0";export const RUNTIME_PARITY_MANIFEST_RAW_SHA256="
|
|
1
|
+
export const RUNTIME_MESSAGE_CHANNEL_REVISION="beeos.runtime-message-channel.v2.0.0";export const RUNTIME_MESSAGE_CHANNEL_RAW_SHA256="dd791ce5f49b7bee1dba21a71e7b2cfbf4db7d77cb787aab5f04c7f4b0e3101b";export const RUNTIME_MESSAGE_CHANNEL_SHA256="e950f1a86bf2bd8bf472603a91111c15b920fcac4c06fd8ac70e2c3f4c3a408f";export const RUNTIME_AUTHORITY_PORTS_REVISION="beeos.runtime-authority-ports.v2.0.0";export const RUNTIME_AUTHORITY_PORTS_RAW_SHA256="a2e9565ae617bcaeb4d837fe176a3602be041913d28a3f0a3a9ec2e3dae0d7b4";export const RUNTIME_AUTHORITY_PORTS_SHA256="3bd582f1f6babcdbe953a082faf813247c960f6bbf4c0f713e7fd92e27d163f5";export const RUNTIME_SESSION_CANCEL_REVISION="beeos.runtime-session-cancel.v1.0.0";export const RUNTIME_SESSION_CANCEL_SHA256="ad32581546f3a97d62df3a6785e3ec057e7dd888b31885f46cfb43d07c966d3e";export const RUNTIME_PARITY_MANIFEST_REVISION="beeos.runtime-parity.v1.1.0";export const RUNTIME_PARITY_MANIFEST_RAW_SHA256="f1030e7bf2084f584d558c22b9bffde0f823d6950c696a6f0571adaffcdbcee0";export const RUNTIME_PARITY_MANIFEST_SHA256="c98ed2aa822b29530cb02badd51654f2766f1dc0ff2c53b660be6431b1f23747";const manifestEntries=[{method:"session/new",acpSource:"service",route:"POST /api/v1/runtime/conversations",contractRevision:RUNTIME_AUTHORITY_PORTS_REVISION,status:"ready",blockerOwner:""},{method:"session/set_mode",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"agent/create",acpSource:"service",route:"POST /api/v1/agents/sync",contractRevision:RUNTIME_AUTHORITY_PORTS_REVISION,status:"ready",blockerOwner:""},{method:"agent/update",acpSource:"service",route:"POST /api/v1/agents/sync",contractRevision:RUNTIME_AUTHORITY_PORTS_REVISION,status:"ready",blockerOwner:""},{method:"agent/delete",acpSource:"service",route:"POST /api/v1/agents/sync",contractRevision:RUNTIME_AUTHORITY_PORTS_REVISION,status:"ready",blockerOwner:""},{method:"agent/applyTemplate",acpSource:"service",route:"POST /api/v1/agents/sync",contractRevision:RUNTIME_AUTHORITY_PORTS_REVISION,status:"ready",blockerOwner:""},{method:"skills/list",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"skills/install",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"skills/uninstall",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"skills/update",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"models/list",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"cron/list",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"cron/status",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"cron/add",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"cron/update",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"cron/remove",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"cron/run",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"cron/runs",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"mcp/list",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"mcp/prepare",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"mcp/set",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"mcp/unset",acpSource:"service",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""},{method:"session/clear",acpSource:"conversation",route:"POST /api/v1/runtime/conversations/{conversationId}/history-boundary/{action}",contractRevision:RUNTIME_AUTHORITY_PORTS_REVISION,status:"ready",blockerOwner:""},{method:"session/set_model",acpSource:"conversation",route:"POST /api/v1/runtime/conversations/{conversationId}/metadata/model",contractRevision:RUNTIME_AUTHORITY_PORTS_REVISION,status:"ready",blockerOwner:""},{method:"session/cancel",acpSource:"conversation",route:"POST /api/v1/runtime/operations",contractRevision:RUNTIME_MESSAGE_CHANNEL_REVISION,status:"ready",blockerOwner:""}];export const RUNTIME_PARITY_MANIFEST=Object.freeze(manifestEntries.map(e=>Object.freeze(e)));export const RUNTIME_PARITY_READY_METHODS=Object.freeze(new Set(RUNTIME_PARITY_MANIFEST.filter(e=>"ready"===e.status).map(e=>e.method)));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash,createPrivateKey,randomUUID}from"node:crypto";import{join}from"node:path";import{CONVERSATION_RUNTIME_CANONICAL_COMMAND_NAMES,RUNTIME_METHOD_PARITY_MANIFEST,RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION,RUNTIME_RPC_CONTRACT_REVISION}from"@beeos-ai/beeos-types/runtime";import{agentBoundFetch}from"../agent-auth.js";import{FileRuntimeCommandJournal}from"./runtime-command-journal.js";import{FileRuntimeAgentIdentityRegistry}from"./runtime-agent-identity-registry.js";import{RuntimeRegistrationIdentityStore}from"./runtime-registration-identity-store.js";import{InstanceAuthorityRuntimeRegistrationTransport,RuntimeRegistrationCoordinator,RuntimeRegistrationJournalAdvanceRequiredError}from"./runtime-registration.js";import{verifiedRuntimeParityManifestDigest}from"./runtime-parity-manifest-digest.js";import{intersectRuntimeServiceMethodsWithBackendCapabilities}from"./runtime-service-contract-compatibility.js";export function cloudRuntimeTargetInstanceId(t){const e=t.BEEOS_CLOUD_RUNTIME_INSTANCE_ID;if(void 0!==e){if(!/^[A-Za-z0-9_-]{1,128}$/.test(e)||e!==t.BEEOS_INSTANCE_ID)throw new Error("Cloud runtime target must match the provisioned BeeOS instance identity");return e}}export class RuntimeProductionAuthority{options;journal;identities;identityStore;handlerIdentity;listeners=new Set;coordinator;unsubscribeCoordinator;starting;rolling=new Map;refreshing;stoppedCoordinators=new WeakSet;coordinatorGeneration=0;lineage;identity;preparing;runtimeConsumerLive=!1;runtimeServiceMethods=Object.freeze([]);realtimeCapabilityReady=new Map;resourceBindingContractRevision;manifestDigest=verifiedRuntimeParityManifestDigest();started=!1;lifecycleVersion=0;authorityLeasePending=!1;boundAgentFetch;constructor(t){if(this.options=t,void 0!==t.targetInstanceId&&!/^[A-Za-z0-9_-]{1,128}$/.test(t.targetInstanceId))throw new Error("Cloud runtime target instance ID is invalid");this.handlerIdentity=t.handlerIdentity??(process.env.HOSTNAME?.trim()||process.env.POD_NAME?.trim()||randomUUID()),this.journal=new FileRuntimeCommandJournal(join(t.stateDirectory,"runtime-command-journal.json"),void 0,void 0,{onMaintenanceError:e=>{const i=`[runtime-journal] event=checkpoint_failed trigger=threshold error=${e instanceof Error?e.message:String(e)}`;t.logger?.error?t.logger.error(i):t.logger?.warn?.(i)}}),this.identities=new FileRuntimeAgentIdentityRegistry(join(t.stateDirectory,"runtime-agent-identities.json")),this.boundAgentFetch=t.boundAgentFetch??((e,i)=>agentBoundFetch(e,t.keys,i)),this.identityStore=new RuntimeRegistrationIdentityStore(join(t.stateDirectory,"runtime-registration-identity.json"))}get agentKeys(){return this.options.keys}get stateDirectory(){return this.options.stateDirectory}get cloudTargetInstanceId(){return this.options.targetInstanceId}get authorityLease(){return this.coordinator?.authorityLease??null}subscribeAuthority(t){return this.listeners.add(t),()=>{this.listeners.delete(t)}}currentConsumerBinding(){return this.identity&&this.lineage?this.consumerBinding(this.identity,this.lineage):null}async prepareConsumerBinding(){return this.preparing||(this.preparing=(async()=>{const t=await this.identityStore.acquire(this.handlerIdentity,this.journal),e={journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration};return this.lineage=e,this.identity=t,this.consumerBinding(t,e)})().finally(()=>{this.preparing=void 0})),await this.preparing}setRuntimeConsumerLive(t){if(this.started)throw new Error("runtime consumer availability is immutable while registered");this.runtimeConsumerLive=t}setRuntimeServiceMethods(t){if(this.started)throw new Error("runtime Service methods are immutable while registered");this.runtimeServiceMethods=intersectRuntimeServiceMethodsWithBackendCapabilities(t)}setRuntimeRealtimeCapabilityReady(t,e){const i=this.realtimeCapabilityReady.get(t)!==e;if(this.realtimeCapabilityReady.set(t,e),!i||!this.started)return;const r=this.lifecycleVersion;this.refreshRealtimeCapabilities(r).catch(t=>this.options.logger?.warn?.(`[runtime-authority] authority lease refresh fenced (realtime capability): ${t instanceof Error?t.message:t}`))}setRuntimeResourceBindingContractRevision(t){if(this.started)throw new Error("runtime resource binding revision is immutable while registered");if(void 0!==t&&t!==RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION)throw new Error("unsupported runtime resource binding revision");this.resourceBindingContractRevision=t}async start(t){if(this.starting)return await this.starting;if(this.started)return;if(t?.aborted)return;const e=this.lifecycleVersion,i=this.startOnce(e,t).finally(()=>{this.starting===i&&(this.starting=void 0)});this.starting=i,await i}stop(){this.lifecycleVersion++,this.starting=void 0,this.started=!1;const t=this.coordinator;t&&this.detachCoordinator(t),this.publish(null)}async startOnce(t,e){if(await this.prepareConsumerBinding(),t!==this.lifecycleVersion||e?.aborted)return;this.lineage;const i=this.identity;this.started=!0,await this.activate(i,t)}async activate(t,e){if(!this.isLifecycleCurrent(e))return;if(this.resourceBindingContractRevision&&!this.runtimeConsumerLive)throw new Error("resource binding revision requires a live Message Service consumer");if(!this.runtimeConsumerLive||0===this.runtimeServiceMethods.length)throw new Error(`runtime registration refused: consumerLive=${this.runtimeConsumerLive} methods=${this.runtimeServiceMethods.length}`);const i=[...this.runtimeServiceMethods],r=runtimeCapabilities(this.runtimeServiceMethods,this.realtimeCapabilityReady);this.options.logger?.info?.(`[runtime-authority] advertising ${i.length} methods (renew-safe)`);const n=++this.coordinatorGeneration,o=new RuntimeRegistrationCoordinator(new InstanceAuthorityRuntimeRegistrationTransport({agentGatewayUrl:this.options.agentGatewayUrl,registrationId:t.registrationId,agentFetch:this.options.agentFetch}),{registrationId:t.registrationId,handlerIdentity:t.handlerIdentity,contractRevision:RUNTIME_RPC_CONTRACT_REVISION,runtimeMethods:i,capabilities:r,manifestDigest:this.manifestDigest,journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration,instanceIdentityKeyId:createHash("sha256").update(this.options.keys.publicKey).digest("hex"),targetInstanceId:this.options.targetInstanceId,privateKey:createPrivateKey({key:privateKeyDer(this.options.keys.privateKey),format:"der",type:"pkcs8"}),getMSConnectionStatus:this.options.getMSConnectionStatus},(t,i)=>{if(!this.isCoordinatorCurrent(e,n,o))return;const r=i instanceof Error?i.message:void 0!==i?String(i):"";this.options.logger?.warn?.(r?`[runtime-authority] lease lost: ${t}: ${r}`:`[runtime-authority] lease lost: ${t}`);const s=i instanceof RuntimeRegistrationJournalAdvanceRequiredError?i:void 0;("expired"===t||s)&&this.rollExpired(e,n,o,s).catch(t=>this.options.logger?.warn?.(`[runtime-authority] authority lease roll fenced (expired registration): ${t instanceof Error?t.message:t}`))});this.coordinator=o,this.unsubscribeCoordinator=o.subscribeAuthority(t=>{this.isCoordinatorCurrent(e,n,o)&&(t&&this.authorityLeasePending?(this.authorityLeasePending=!1,this.options.logger?.info?.("[runtime-authority] registration active (recovered after handoff)")):t||(this.authorityLeasePending=!0),this.publish(t))});const s=await o.start();this.isCoordinatorCurrent(e,n,o)?(this.options.logger?.info?.("[runtime-authority] registration "+(s?"active":"pending")),s||(this.authorityLeasePending=!0)):this.stopCoordinatorOnce(o)}async rollExpired(t,e,i,r){if(!this.lineage||!this.isCoordinatorCurrent(t,e,i))return;const n=this.rolling.get(e);if(n)return await n;let o=!1;const s=(async()=>{if(!this.isCoordinatorCurrent(t,e,i))return;this.detachCoordinator(i),o=!0;const n=this.identity;if(!n)return;const s=await this.identityStore.roll(n,this.journal,{authorityCurrentGeneration:r?.currentJournalGeneration,expectedJournalGeneration:r?.expectedJournalGeneration});this.isLifecycleCurrent(t)&&void 0===this.coordinator&&(this.identity=s,this.lineage={journalStoreId:s.journalStoreId,journalGeneration:s.journalGeneration},await this.activate(s,t))})().finally(()=>{this.rolling.get(e)===s&&this.rolling.delete(e),o&&this.publishDetachedWithoutLease("expired registration roll")});this.rolling.set(e,s),await s}async refreshRealtimeCapabilities(t){if(!this.isLifecycleCurrent(t))return;const e=this.refreshing;if(e)return await e;let i=!1;const r=(async()=>{if(!this.isLifecycleCurrent(t))return;const e=this.identity,r=this.coordinator;e&&r&&(r.authorityLease?(this.detachCoordinator(r),i=!0,this.isLifecycleCurrent(t)&&void 0===this.coordinator&&await this.activate(e,t)):this.options.logger?.info?.("[runtime-authority] deferring realtime capability refresh until registration is active"))})().finally(()=>{this.refreshing===r&&(this.refreshing=void 0),i&&this.publishDetachedWithoutLease("realtime capability refresh")});this.refreshing=r,await r}isLifecycleCurrent(t){return this.started&&t===this.lifecycleVersion}isCoordinatorCurrent(t,e,i){return this.isLifecycleCurrent(t)&&this.coordinatorGeneration===e&&this.coordinator===i}detachCoordinator(t){this.coordinator===t&&(this.unsubscribeCoordinator?.(),this.unsubscribeCoordinator=void 0,this.coordinator=void 0),this.stopCoordinatorOnce(t)}publishDetachedWithoutLease(t){null===this.authorityLease&&(this.authorityLeasePending=!0,this.options.logger?.warn?.(`[runtime-authority] authority lease cleared with no live successor lease (${t})`),this.publish(null))}stopCoordinatorOnce(t){this.stoppedCoordinators.has(t)||(this.stoppedCoordinators.add(t),t.stop())}publish(t){for(const e of this.listeners)try{e(t)}catch{}}consumerBinding(t,e){return Object.freeze({handlerIdentity:t.handlerIdentity,journalStoreId:e.journalStoreId,journalGeneration:e.journalGeneration})}}const ED25519_PKCS8_PREFIX=Buffer.from("302e020100300506032b657004220420","hex"),privateKeyDer=t=>32===t.length?Buffer.concat([ED25519_PKCS8_PREFIX,Buffer.from(t)]):Buffer.from(t),REALTIME_CAPABILITY_NAMES=["terminal","canvas"];function runtimeCapabilities(t,e){const i=new Set(t),r=RUNTIME_METHOD_PARITY_MANIFEST.filter(t=>t.serviceAllowed&&void 0!==runtimeInvocationMethod(t)&&i.has(runtimeInvocationMethod(t))).map(t=>t.capability),n=REALTIME_CAPABILITY_NAMES.filter(t=>!0===e.get(t));return[...new Set([...r,...n])]}function runtimeInvocationMethod(t){return"methods"===t.serviceRoute&&t.serviceMethod?t.serviceMethod:Object.entries(CONVERSATION_RUNTIME_CANONICAL_COMMAND_NAMES).find(([,e])=>e===t.canonicalCommand)?.[0]}
|
|
1
|
+
import{createHash,randomUUID}from"node:crypto";import{join}from"node:path";import{CONVERSATION_RUNTIME_CANONICAL_COMMAND_NAMES,RUNTIME_METHOD_PARITY_MANIFEST,RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION,RUNTIME_RPC_CONTRACT_REVISION}from"@beeos-ai/beeos-types/runtime";import{FileRuntimeCommandJournal}from"./runtime-command-journal.js";import{FileRuntimeAgentIdentityRegistry}from"./runtime-agent-identity-registry.js";import{RuntimeRegistrationIdentityStore}from"./runtime-registration-identity-store.js";import{InstanceAuthorityRuntimeRegistrationTransport,RuntimeRegistrationCoordinator,RuntimeRegistrationJournalAdvanceRequiredError,signAgentMessage}from"@beeos-ai/cloud-harness-sdk";import{verifiedRuntimeParityManifestDigest}from"./runtime-parity-manifest-digest.js";import{intersectRuntimeServiceMethodsWithBackendCapabilities}from"./runtime-service-contract-compatibility.js";export function cloudRuntimeTargetInstanceId(t){if(void 0!==t){if(!/^[A-Za-z0-9_-]{1,128}$/.test(t))throw new Error("Cloud runtime target must match the provisioned BeeOS instance identity");return t}}export class RuntimeProductionAuthority{options;journal;identities;identityStore;handlerIdentity;listeners=new Set;coordinator;unsubscribeCoordinator;starting;rolling=new Map;refreshing;stoppedCoordinators=new WeakSet;coordinatorGeneration=0;lineage;identity;preparing;runtimeConsumerLive=!1;runtimeServiceMethods=Object.freeze([]);realtimeCapabilityReady=new Map;resourceBindingContractRevision;manifestDigest=verifiedRuntimeParityManifestDigest();started=!1;lifecycleVersion=0;authorityLeasePending=!1;constructor(t){if(this.options=t,void 0!==t.targetInstanceId&&!/^[A-Za-z0-9_-]{1,128}$/.test(t.targetInstanceId))throw new Error("Cloud runtime target instance ID is invalid");this.handlerIdentity=t.handlerIdentity??(process.env.HOSTNAME?.trim()||process.env.POD_NAME?.trim()||randomUUID()),this.journal=new FileRuntimeCommandJournal(join(t.stateDirectory,"runtime-command-journal.json"),void 0,void 0,{onMaintenanceError:e=>{const i=`[runtime-journal] event=checkpoint_failed trigger=threshold error=${e instanceof Error?e.message:String(e)}`;t.logger?.error?t.logger.error(i):t.logger?.warn?.(i)}}),this.identities=new FileRuntimeAgentIdentityRegistry(join(t.stateDirectory,"runtime-agent-identities.json")),this.identityStore=new RuntimeRegistrationIdentityStore(join(t.stateDirectory,"runtime-registration-identity.json"))}get agentKeys(){return this.options.keys}get stateDirectory(){return this.options.stateDirectory}get cloudTargetInstanceId(){return this.options.targetInstanceId}bindCloudTarget(t){if(void 0!==this.options.targetInstanceId){if(this.options.targetInstanceId!==t)throw new Error("Cloud runtime authority target changed during process lifetime")}else this.options.targetInstanceId=t}get authorityLease(){return this.coordinator?.authorityLease??null}subscribeAuthority(t){return this.listeners.add(t),()=>{this.listeners.delete(t)}}currentConsumerBinding(){return this.identity&&this.lineage?this.consumerBinding(this.identity,this.lineage):null}async prepareConsumerBinding(){return this.preparing||(this.preparing=(async()=>{const t=await this.identityStore.acquire(this.handlerIdentity,this.journal),e={journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration};return this.lineage=e,this.identity=t,this.consumerBinding(t,e)})().finally(()=>{this.preparing=void 0})),await this.preparing}setRuntimeConsumerLive(t){if(this.started)throw new Error("runtime consumer availability is immutable while registered");this.runtimeConsumerLive=t}setRuntimeServiceMethods(t){if(this.started)throw new Error("runtime Service methods are immutable while registered");this.runtimeServiceMethods=intersectRuntimeServiceMethodsWithBackendCapabilities(t)}setRuntimeRealtimeCapabilityReady(t,e){const i=this.realtimeCapabilityReady.get(t)!==e;if(this.realtimeCapabilityReady.set(t,e),!i||!this.started)return;const r=this.lifecycleVersion;this.refreshRealtimeCapabilities(r).catch(t=>this.options.logger?.warn?.(`[runtime-authority] authority lease refresh fenced (realtime capability): ${t instanceof Error?t.message:t}`))}setRuntimeResourceBindingContractRevision(t){if(this.started)throw new Error("runtime resource binding revision is immutable while registered");if(void 0!==t&&t!==RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION)throw new Error("unsupported runtime resource binding revision");this.resourceBindingContractRevision=t}async start(t){if(this.starting)return await this.starting;if(this.started)return;if(t?.aborted)return;const e=this.lifecycleVersion,i=this.startOnce(e,t).finally(()=>{this.starting===i&&(this.starting=void 0)});this.starting=i,await i}stop(){this.lifecycleVersion++,this.starting=void 0,this.started=!1;const t=this.coordinator;t&&this.detachCoordinator(t),this.publish(null)}async startOnce(t,e){if(await this.prepareConsumerBinding(),t!==this.lifecycleVersion||e?.aborted)return;this.lineage;const i=this.identity;this.started=!0,await this.activate(i,t)}async activate(t,e){if(!this.isLifecycleCurrent(e))return;if(this.resourceBindingContractRevision&&!this.runtimeConsumerLive)throw new Error("resource binding revision requires a live Message Service consumer");if(!this.runtimeConsumerLive||0===this.runtimeServiceMethods.length)throw new Error(`runtime registration refused: consumerLive=${this.runtimeConsumerLive} methods=${this.runtimeServiceMethods.length}`);const i=[...this.runtimeServiceMethods],r=runtimeCapabilities(this.runtimeServiceMethods,this.realtimeCapabilityReady);this.options.logger?.info?.(`[runtime-authority] advertising ${i.length} methods (renew-safe)`);const n=++this.coordinatorGeneration,o=new RuntimeRegistrationCoordinator(new InstanceAuthorityRuntimeRegistrationTransport({gateway:this.options.gateway,registrationId:t.registrationId}),{registrationId:t.registrationId,handlerIdentity:t.handlerIdentity,contractRevision:RUNTIME_RPC_CONTRACT_REVISION,runtimeMethods:i,capabilities:r,manifestDigest:this.manifestDigest,journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration,instanceIdentityKeyId:createHash("sha256").update(this.options.keys.publicKey).digest("hex"),targetInstanceId:this.options.targetInstanceId,signIdentityProof:t=>signAgentMessage(t,this.options.keys.privateKey),getMSConnectionStatus:this.options.getMSConnectionStatus},(t,i)=>{if(!this.isCoordinatorCurrent(e,n,o))return;const r=i instanceof Error?i.message:void 0!==i?String(i):"";this.options.logger?.warn?.(r?`[runtime-authority] lease lost: ${t}: ${r}`:`[runtime-authority] lease lost: ${t}`);const s=i instanceof RuntimeRegistrationJournalAdvanceRequiredError?i:void 0;("expired"===t||s)&&this.rollExpired(e,n,o,s).catch(t=>this.options.logger?.warn?.(`[runtime-authority] authority lease roll fenced (expired registration): ${t instanceof Error?t.message:t}`))});this.coordinator=o,this.unsubscribeCoordinator=o.subscribeAuthority(t=>{this.isCoordinatorCurrent(e,n,o)&&(t&&this.authorityLeasePending?(this.authorityLeasePending=!1,this.options.logger?.info?.("[runtime-authority] registration active (recovered after handoff)")):t||(this.authorityLeasePending=!0),this.publish(t))});const s=await o.start();this.isCoordinatorCurrent(e,n,o)?(this.options.logger?.info?.("[runtime-authority] registration "+(s?"active":"pending")),s||(this.authorityLeasePending=!0)):this.stopCoordinatorOnce(o)}async rollExpired(t,e,i,r){if(!this.lineage||!this.isCoordinatorCurrent(t,e,i))return;const n=this.rolling.get(e);if(n)return await n;let o=!1,s=!1;const a=(async()=>{if(!this.isCoordinatorCurrent(t,e,i))return;this.detachCoordinator(i),o=!0;const n=this.identity;if(!n)return;let a,h=0;for(;;){if(!this.isLifecycleCurrent(t)||void 0!==this.coordinator)return;try{a=await this.identityStore.roll(n,this.journal,{authorityCurrentGeneration:r?.currentJournalGeneration,expectedJournalGeneration:r?.expectedJournalGeneration});break}catch(t){if(!isRetryableRegistrationRollError(t))throw t;s||(this.publishDetachedWithoutLease("expired registration roll retry"),s=!0),this.options.logger?.warn?.(`[runtime-authority] retrying durable registration roll: ${t instanceof Error?t.message:t}`),await new Promise(t=>setTimeout(t,Math.min(250*2**Math.min(h++,4),4e3)))}}this.isLifecycleCurrent(t)&&void 0===this.coordinator&&(this.identity=a,this.lineage={journalStoreId:a.journalStoreId,journalGeneration:a.journalGeneration},await this.activate(a,t))})().finally(()=>{this.rolling.get(e)===a&&this.rolling.delete(e),o&&!s&&this.publishDetachedWithoutLease("expired registration roll")});this.rolling.set(e,a),await a}async refreshRealtimeCapabilities(t){if(!this.isLifecycleCurrent(t))return;const e=this.refreshing;if(e)return await e;let i=!1;const r=(async()=>{if(!this.isLifecycleCurrent(t))return;const e=this.identity,r=this.coordinator;e&&r&&(r.authorityLease?(this.detachCoordinator(r),i=!0,this.isLifecycleCurrent(t)&&void 0===this.coordinator&&await this.activate(e,t)):this.options.logger?.info?.("[runtime-authority] deferring realtime capability refresh until registration is active"))})().finally(()=>{this.refreshing===r&&(this.refreshing=void 0),i&&this.publishDetachedWithoutLease("realtime capability refresh")});this.refreshing=r,await r}isLifecycleCurrent(t){return this.started&&t===this.lifecycleVersion}isCoordinatorCurrent(t,e,i){return this.isLifecycleCurrent(t)&&this.coordinatorGeneration===e&&this.coordinator===i}detachCoordinator(t){this.coordinator===t&&(this.unsubscribeCoordinator?.(),this.unsubscribeCoordinator=void 0,this.coordinator=void 0),this.stopCoordinatorOnce(t)}publishDetachedWithoutLease(t){null===this.authorityLease&&(this.authorityLeasePending=!0,this.options.logger?.warn?.(`[runtime-authority] authority lease cleared with no live successor lease (${t})`),this.publish(null))}stopCoordinatorOnce(t){this.stoppedCoordinators.has(t)||(this.stoppedCoordinators.add(t),t.stop())}publish(t){for(const e of this.listeners)try{e(t)}catch{}}consumerBinding(t,e){return Object.freeze({handlerIdentity:t.handlerIdentity,journalStoreId:e.journalStoreId,journalGeneration:e.journalGeneration})}}const REALTIME_CAPABILITY_NAMES=["terminal","canvas"];function isRetryableRegistrationRollError(t){return t instanceof Error&&(t.message.includes("owned directory lock lease expired")||t.message.includes("owned directory lock was fenced")||t.message.includes("timed out acquiring lock")||t.message.includes("owned directory lock is busy"))}function runtimeCapabilities(t,e){const i=new Set(t),r=RUNTIME_METHOD_PARITY_MANIFEST.filter(t=>t.serviceAllowed&&void 0!==runtimeInvocationMethod(t)&&i.has(runtimeInvocationMethod(t))).map(t=>t.capability),n=REALTIME_CAPABILITY_NAMES.filter(t=>!0===e.get(t));return[...new Set([...r,...n])]}function runtimeInvocationMethod(t){return"methods"===t.serviceRoute&&t.serviceMethod?t.serviceMethod:Object.entries(CONVERSATION_RUNTIME_CANONICAL_COMMAND_NAMES).find(([,e])=>e===t.canonicalCommand)?.[0]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID}from"node:crypto";import{mkdir,readFile}from"node:fs/promises";import{dirname}from"node:path";import{withOwnedDirectoryLock}from"./owned-directory-lock.js";import{MonotonicJournalSegments}from"./monotonic-journal-segments.js";export class RuntimeRegistrationIdentityStore{file;createId;segments;constructor(t,e=randomUUID){this.file=t,this.createId=e,this.segments=new MonotonicJournalSegments(t)}async acquire(t,e){if(!t)throw new Error("invalid runtime registration identity inputs");return await mkdir(dirname(this.file),{recursive:!0,mode:448}),await withOwnedDirectoryLock(`${this.file}.lock`,async n=>{const r=await this.segments.authorityFloor(),i=await this.read(),o=await e.lineage();if(i&&i.handlerIdentity===t&&i.journalStoreId===o.journalStoreId&&i.journalGeneration===o.journalGeneration)return identityOf(i);if(i&&i.journalStoreId!==o.journalStoreId)throw new Error("runtime registration journal store changed");const a=i&&BigInt(o.journalGeneration)>BigInt(i.journalGeneration)?o:await e.advanceLineageGeneration({journalStoreId:o.journalStoreId,floor:i?.journalGeneration??o.journalGeneration}),s={version:1,registrationId:this.createId(),handlerIdentity:t,...a,updatedAt:(new Date).toISOString()};return await n.assertOwned(),await this.publish(n.epoch,s,r),identityOf(s)},{epochFloor:()=>this.segments.authorityFloor()})}async roll(t,e,n){if(!(t.handlerIdentity&&t.registrationId&&t.journalStoreId&&/^[1-9][0-9]*$/.test(t.journalGeneration)))throw new Error("invalid runtime registration identity inputs");return await mkdir(dirname(this.file),{recursive:!0,mode:448}),await withOwnedDirectoryLock(`${this.file}.lock`,async r=>{const i=await this.segments.authorityFloor(),o=await this.read();if(!o||identityKey(o)!==identityKey(t))throw new Error("runtime registration identity was fenced by a successor")
|
|
1
|
+
import{randomUUID}from"node:crypto";import{mkdir,readFile}from"node:fs/promises";import{dirname}from"node:path";import{withOwnedDirectoryLock}from"./owned-directory-lock.js";import{MonotonicJournalSegments}from"./monotonic-journal-segments.js";export class RuntimeRegistrationIdentityStore{file;createId;segments;constructor(t,e=randomUUID){this.file=t,this.createId=e,this.segments=new MonotonicJournalSegments(t)}async acquire(t,e){if(!t)throw new Error("invalid runtime registration identity inputs");return await mkdir(dirname(this.file),{recursive:!0,mode:448}),await withOwnedDirectoryLock(`${this.file}.lock`,async n=>{const r=await this.segments.authorityFloor(),i=await this.read(),o=await e.lineage();if(i&&i.handlerIdentity===t&&i.journalStoreId===o.journalStoreId&&i.journalGeneration===o.journalGeneration)return identityOf(i);if(i&&i.journalStoreId!==o.journalStoreId)throw new Error("runtime registration journal store changed");const a=i&&BigInt(o.journalGeneration)>BigInt(i.journalGeneration)?o:await e.advanceLineageGeneration({journalStoreId:o.journalStoreId,floor:i?.journalGeneration??o.journalGeneration}),s={version:1,registrationId:this.createId(),handlerIdentity:t,...a,updatedAt:(new Date).toISOString()};return await n.assertOwned(),await this.publish(n.epoch,s,r),identityOf(s)},{epochFloor:()=>this.segments.authorityFloor()})}async roll(t,e,n){if(!(t.handlerIdentity&&t.registrationId&&t.journalStoreId&&/^[1-9][0-9]*$/.test(t.journalGeneration)))throw new Error("invalid runtime registration identity inputs");return await mkdir(dirname(this.file),{recursive:!0,mode:448}),await withOwnedDirectoryLock(`${this.file}.lock`,async r=>{const i=await this.segments.authorityFloor(),o=await this.read();if(!o||identityKey(o)!==identityKey(t)){if(o&&o.handlerIdentity===t.handlerIdentity&&o.journalStoreId===t.journalStoreId&&BigInt(o.journalGeneration)>BigInt(t.journalGeneration))return identityOf(o);throw new Error("runtime registration identity was fenced by a successor")}const a=await e.lineage();if(a.journalStoreId!==t.journalStoreId||BigInt(a.journalGeneration)<BigInt(t.journalGeneration))throw new Error("runtime registration journal lineage changed");const s=await nextRollLineage(e,a,t,n),d={version:1,registrationId:this.createId(),handlerIdentity:t.handlerIdentity,...s,updatedAt:(new Date).toISOString()};return await r.assertOwned(),await this.publish(r.epoch,d,i),identityOf(d)},{epochFloor:()=>this.segments.authorityFloor()})}async read(){const t=new Map;try{const e=JSON.parse(await readFile(this.file,"utf8"));if(!(1===e.version&&e.registrationId&&e.handlerIdentity&&e.journalStoreId&&/^[1-9][0-9]*$/.test(e.journalGeneration)))throw new Error("invalid runtime registration identity");t.set("snapshot",{value:e,logicalRevision:e.journalGeneration,publisherEpoch:"0"})}catch(t){if("ENOENT"!==t.code)throw t}return(await this.segments.reduce(t)).get("snapshot")?.value??null}async publish(t,e,n){await this.segments.publish(t,[{key:"snapshot",logicalRevision:e.journalGeneration,value:structuredClone(e)}],n),await this.segments.prune()}}const identityOf=t=>({registrationId:t.registrationId,handlerIdentity:t.handlerIdentity,journalStoreId:t.journalStoreId,journalGeneration:t.journalGeneration}),identityKey=t=>`${t.registrationId}\0${t.handlerIdentity}\0${t.journalStoreId}\0${t.journalGeneration}`;async function nextRollLineage(t,e,n,r){const i=r?.expectedJournalGeneration??(r?.authorityCurrentGeneration?String(BigInt(r.authorityCurrentGeneration)+1n):void 0);if(i){const r=BigInt(e.journalGeneration),o=BigInt(i);if(r===o)return e;if(r>o)throw new Error(`runtime registration journal generation overshot authority (local=${r} expected=${o})`);return await t.advanceLineageGeneration({journalStoreId:n.journalStoreId,floor:String(o-1n)})}return BigInt(e.journalGeneration)>BigInt(n.journalGeneration)?e:await t.advanceLineageGeneration({journalStoreId:n.journalStoreId,floor:n.journalGeneration})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash}from"node:crypto";import{readFileSync}from"node:fs";import{RUNTIME_METHOD_PARITY_MANIFEST,RUNTIME_RPC_CONTRACT_REVISION}from"@beeos-ai/beeos-types/runtime";import{RUNTIME_AUTHORITY_PORTS_REVISION,RUNTIME_AUTHORITY_PORTS_RAW_SHA256,RUNTIME_AUTHORITY_PORTS_SHA256,RUNTIME_MESSAGE_CHANNEL_REVISION,RUNTIME_MESSAGE_CHANNEL_RAW_SHA256,RUNTIME_MESSAGE_CHANNEL_SHA256,RUNTIME_PARITY_MANIFEST,RUNTIME_PARITY_MANIFEST_RAW_SHA256,RUNTIME_PARITY_MANIFEST_REVISION,RUNTIME_PARITY_MANIFEST_SHA256,RUNTIME_PARITY_READY_METHODS,RUNTIME_SESSION_CANCEL_REVISION,RUNTIME_SESSION_CANCEL_SHA256}from"./runtime-parity-manifest.js";import{verifiedRuntimeParityManifestDigest}from"./runtime-parity-manifest-digest.js";export const RUNTIME_SERVICE_WIRE_CONTRACT_ARTIFACTS=Object.freeze([Object.freeze({revision:RUNTIME_MESSAGE_CHANNEL_REVISION,sha256:RUNTIME_MESSAGE_CHANNEL_SHA256,rawSha256:RUNTIME_MESSAGE_CHANNEL_RAW_SHA256}),Object.freeze({revision:RUNTIME_AUTHORITY_PORTS_REVISION,sha256:RUNTIME_AUTHORITY_PORTS_SHA256,rawSha256:RUNTIME_AUTHORITY_PORTS_RAW_SHA256}),Object.freeze({revision:RUNTIME_SESSION_CANCEL_REVISION,sha256:RUNTIME_SESSION_CANCEL_SHA256}),Object.freeze({revision:RUNTIME_PARITY_MANIFEST_REVISION,sha256:RUNTIME_PARITY_MANIFEST_SHA256})]);export function loadRuntimeServiceContractIdentity(){return verifyPackagedRuntimeServiceWireIdentity(),Object.freeze({contractRevision:RUNTIME_RPC_CONTRACT_REVISION,canonicalManifestDigest:verifiedRuntimeParityManifestDigest(),wireArtifacts:RUNTIME_SERVICE_WIRE_CONTRACT_ARTIFACTS})}const RUNTIME_SERVICE_WIRE_IDENTITY_RAW_SHA256="
|
|
1
|
+
import{createHash}from"node:crypto";import{readFileSync}from"node:fs";import{RUNTIME_METHOD_PARITY_MANIFEST,RUNTIME_RPC_CONTRACT_REVISION}from"@beeos-ai/beeos-types/runtime";import{RUNTIME_AUTHORITY_PORTS_REVISION,RUNTIME_AUTHORITY_PORTS_RAW_SHA256,RUNTIME_AUTHORITY_PORTS_SHA256,RUNTIME_MESSAGE_CHANNEL_REVISION,RUNTIME_MESSAGE_CHANNEL_RAW_SHA256,RUNTIME_MESSAGE_CHANNEL_SHA256,RUNTIME_PARITY_MANIFEST,RUNTIME_PARITY_MANIFEST_RAW_SHA256,RUNTIME_PARITY_MANIFEST_REVISION,RUNTIME_PARITY_MANIFEST_SHA256,RUNTIME_PARITY_READY_METHODS,RUNTIME_SESSION_CANCEL_REVISION,RUNTIME_SESSION_CANCEL_SHA256}from"./runtime-parity-manifest.js";import{verifiedRuntimeParityManifestDigest}from"./runtime-parity-manifest-digest.js";export const RUNTIME_SERVICE_WIRE_CONTRACT_ARTIFACTS=Object.freeze([Object.freeze({revision:RUNTIME_MESSAGE_CHANNEL_REVISION,sha256:RUNTIME_MESSAGE_CHANNEL_SHA256,rawSha256:RUNTIME_MESSAGE_CHANNEL_RAW_SHA256}),Object.freeze({revision:RUNTIME_AUTHORITY_PORTS_REVISION,sha256:RUNTIME_AUTHORITY_PORTS_SHA256,rawSha256:RUNTIME_AUTHORITY_PORTS_RAW_SHA256}),Object.freeze({revision:RUNTIME_SESSION_CANCEL_REVISION,sha256:RUNTIME_SESSION_CANCEL_SHA256}),Object.freeze({revision:RUNTIME_PARITY_MANIFEST_REVISION,sha256:RUNTIME_PARITY_MANIFEST_SHA256})]);export function loadRuntimeServiceContractIdentity(){return verifyPackagedRuntimeServiceWireIdentity(),Object.freeze({contractRevision:RUNTIME_RPC_CONTRACT_REVISION,canonicalManifestDigest:verifiedRuntimeParityManifestDigest(),wireArtifacts:RUNTIME_SERVICE_WIRE_CONTRACT_ARTIFACTS})}const RUNTIME_SERVICE_WIRE_IDENTITY_RAW_SHA256="edf6b139618b481051761403ce71dbb61c67b23bb319464fedf5fddaebe10b72";function verifyPackagedRuntimeServiceWireIdentity(){verifyRuntimeServiceWireIdentityBytes(readFileSync(new URL("../../runtime-service-wire-identity.v1.json",import.meta.url)))}export function verifyRuntimeServiceWireIdentityBytes(e){if(createHash("sha256").update(e).digest("hex")!==RUNTIME_SERVICE_WIRE_IDENTITY_RAW_SHA256)throw new Error("packaged runtime Service wire identity bytes drifted");const i=JSON.parse(Buffer.from(e).toString("utf8"));if(1!==i.schemaVersion||"RFC8785/JCS"!==i.canonicalization||"SHA-256"!==i.hashAlgorithm||"@beeos-ai/beeos-types"!==i.canonicalTypes?.package||"4.4.2-cloud.3"!==i.canonicalTypes.version||i.canonicalTypes.runtimeRpcContractRevision!==RUNTIME_RPC_CONTRACT_REVISION||"f75832c57a18ca614e946a3b1d194828df76d600907f378efe28633df94146fc"!==i.canonicalTypes.runtimeMethodManifestRawSHA256||i.canonicalTypes.runtimeMethodManifestJcsSHA256!==verifiedRuntimeParityManifestDigest())throw new Error("packaged runtime Service canonical Types identity drifted");const t=new Map([["runtime-parity-manifest",["openapi/runtime-parity-manifest-v1.json",RUNTIME_PARITY_MANIFEST_REVISION,RUNTIME_PARITY_MANIFEST_RAW_SHA256,RUNTIME_PARITY_MANIFEST_SHA256]],["runtime-message-channel",["openapi/runtime-message-channel-v1.contract.json",RUNTIME_MESSAGE_CHANNEL_REVISION,RUNTIME_MESSAGE_CHANNEL_RAW_SHA256,RUNTIME_MESSAGE_CHANNEL_SHA256]],["runtime-authority-ports",["openapi/runtime-authority-ports-v1.contract.json",RUNTIME_AUTHORITY_PORTS_REVISION,RUNTIME_AUTHORITY_PORTS_RAW_SHA256,RUNTIME_AUTHORITY_PORTS_SHA256]]]);if(!Array.isArray(i.artifacts)||i.artifacts.length!==t.size)throw new Error("packaged runtime Service wire artifact set drifted");for(const e of i.artifacts){const i=t.get(e.name);if(!i||e.path!==i[0]||e.revision!==i[1]||e.rawSHA256!==i[2]||e.jcsSHA256!==i[3])throw new Error(`packaged runtime Service wire artifact ${e.name||"<missing>"} drifted`);t.delete(e.name)}if(0!==t.size)throw new Error("packaged runtime Service wire artifact is missing")}export function intersectRuntimeServiceMethodsWithBackendCapabilities(e){const i=RUNTIME_PARITY_READY_METHODS,t=new Set(RUNTIME_PARITY_MANIFEST.map(e=>e.method)),r=new Set;for(const e of RUNTIME_METHOD_PARITY_MANIFEST)e.serviceAllowed&&t.has(e.acpMethod)&&(e.minimumRuntimeContractRevision&&e.minimumRuntimeContractRevision!==RUNTIME_RPC_CONTRACT_REVISION||r.add(e.acpMethod));return Object.freeze([...new Set(e)].filter(e=>i.has(e)&&r.has(e)))}export function runtimeServiceContractRequirement(){return`Types ${RUNTIME_RPC_CONTRACT_REVISION}; canonical-manifest ${verifiedRuntimeParityManifestDigest()}; `+RUNTIME_SERVICE_WIRE_CONTRACT_ARTIFACTS.map(e=>`${e.revision}:${e.sha256}`).join("; ")}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION}from"@beeos-ai/beeos-types/runtime";import{parseAndValidateTemplatePackage}from"../acp-gateway/agent-template-package.js";import{HttpRuntimeOperationResourceResolver,RuntimeResourceResolutionError}from"./runtime-operation-resource-resolver.js";import{MessageServiceConversationClearHttpAuthority}from"./message-service-conversation-clear-http-authority.js";import{MessageServiceConversationHistoryBoundary}from"./message-service-conversation-history-boundary.js";import{MessageServiceSessionModelHttpAuthority}from"./message-service-session-model-http-authority.js";import{MsRuntimeMessageChannelConsumerFactory}from"./ms-runtime-message-channel-consumer-factory.js";import{
|
|
1
|
+
import{RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION}from"@beeos-ai/beeos-types/runtime";import{TemplatePackageError,parseAndValidateTemplatePackage}from"../acp-gateway/agent-template-package.js";import{HttpRuntimeOperationResourceResolver,RuntimeResourceResolutionError}from"./runtime-operation-resource-resolver.js";import{CloudGatewayGrantJwksVerifier,GatewayGrantJwksVerifier,RuntimeJwksVerifier,createCloudGrantVerifier,warmGrantJwks}from"@beeos-ai/cloud-harness-sdk";import{fetchRuntimeLeaseAttempt}from"./message-service-runtime-authenticated-fetch.js";import{MessageServiceConversationClearHttpAuthority}from"./message-service-conversation-clear-http-authority.js";import{MessageServiceConversationHistoryBoundary}from"./message-service-conversation-history-boundary.js";import{MessageServiceSessionModelHttpAuthority}from"./message-service-session-model-http-authority.js";import{MsRuntimeMessageChannelConsumerFactory}from"./ms-runtime-message-channel-consumer-factory.js";import{RUNTIME_MESSAGE_CHANNEL_REVISION,RUNTIME_PARITY_MANIFEST}from"./runtime-parity-manifest.js";import{intersectRuntimeServiceMethodsWithBackendCapabilities,loadRuntimeServiceContractIdentity,runtimeServiceContractRequirement}from"./runtime-service-contract-compatibility.js";const CONTRACT_ARTIFACT_BLOCKER=Object.freeze({id:"contract_artifact_mismatch",owner:"backend",requiredContract:"frozen Types manifest and Service wire artifacts"}),TRANSPORT_BLOCKER=Object.freeze({id:"message_channel_transport",owner:"backend",requiredContract:`${RUNTIME_MESSAGE_CHANNEL_REVISION} HTTP delivery/history/append authority`}),JWKS_BLOCKER=Object.freeze({id:"gateway_grant_jwks",owner:"backend",requiredContract:"Purpose-bound Gateway runtime execution-grant JWKS proxy"}),POISON_JOURNAL_BLOCKER=Object.freeze({id:"poison_journal",owner:"openclaw_runtime_client",requiredContract:"Durable bounded runtime poison-delivery journal"}),grantAdapterOptions=new WeakMap;export class AgentGatewayGrantJwksReadinessAdapter{constructor(e){grantAdapterOptions.set(this,{gateway:e.gateway})}}export class AgentGatewaySplitJwksReadinessAdapter extends AgentGatewayGrantJwksReadinessAdapter{}const transportOptions=new WeakMap;export class RuntimeServiceTransportReadinessAdapter{constructor(e){transportOptions.set(this,{messageService:e.messageService,messageClient:e.messageClient,configuredServiceUrl:e.configuredServiceUrl,scopedDeliveryKey:e.scopedDeliveryKey,gateway:e.gateway})}}const cloudTransportOptions=new WeakMap;export class CloudRuntimeServiceTransportReadinessAdapter{constructor(e){cloudTransportOptions.set(this,{...e})}}const CAPABILITY_BLOCKERS=Object.freeze(RUNTIME_PARITY_MANIFEST.filter(e=>"blocked"===e.status).map(e=>Object.freeze({method:e.method,owner:e.blockerOwner,requiredContract:e.contractRevision})));export async function createRuntimeServiceProductionCandidate(e){try{loadRuntimeServiceContractIdentity()}catch{return{status:"unavailable",blockers:Object.freeze([{...CONTRACT_ARTIFACT_BLOCKER,requiredContract:contractArtifactRequirement()}])}}if(!e.poisonJournal)return{status:"unavailable",blockers:Object.freeze([POISON_JOURNAL_BLOCKER])};const r=e.cloudTransportAdapter?cloudTransportOptions.get(e.cloudTransportAdapter):void 0,t=e.authorizationAdapter?startGatewayGrantJwks(e.authorizationAdapter,Boolean(r),e.onGrantJwksWarm):void 0;if(r){if(!r.configuredServiceUrl)return{status:"unavailable",blockers:Object.freeze([TRANSPORT_BLOCKER,...t?[]:[JWKS_BLOCKER]])};if(!(t instanceof CloudGatewayGrantJwksVerifier))return{status:"unavailable",blockers:Object.freeze([JWKS_BLOCKER])};const n=intersectRuntimeServiceMethodsWithBackendCapabilities(["models/list","agent/create","skills/list","skills/update","skills/uninstall","skills/install"]);return n.includes("models/list")?{status:"ready",blockers:[],capabilityBlockers:[],serviceMethods:n,factory:new MsRuntimeMessageChannelConsumerFactory({runtimeDelivery:r.runtimeDelivery,...r.nativePrompt?{nativePrompt:r.nativePrompt}:{},...r.sessionNewConversation?{sessionNewConversation:r.sessionNewConversation}:{},verifier:t,ports:e.attemptPorts??runtimeMessageAttemptPorts(r,r.configuredServiceUrl),journal:e.commandJournal,allowedMethods:new Set(n),options:{poisonJournal:e.poisonJournal,requestSchemaVersion:2,...e.onConsumerDeliveryError?{onDeliveryError:e.onConsumerDeliveryError}:{},...e.onConsumerLeaseStarvation?{onLeaseStarvation:e.onConsumerLeaseStarvation}:{},...e.onConsumerRequestTerminalAccepted?{onRequestTerminalAccepted:e.onConsumerRequestTerminalAccepted}:{},...e.onConsumerRequestAcknowledged?{onRequestAcknowledged:e.onConsumerRequestAcknowledged}:{},...e.onConsumerRequestFailure?{onRequestFailure:e.onConsumerRequestFailure}:{}}})}:{status:"unavailable",blockers:Object.freeze([CONTRACT_ARTIFACT_BLOCKER])}}const n=e.transportAdapter?transportOptions.get(e.transportAdapter):void 0;if(!n?.messageClient||!n.configuredServiceUrl)return{status:"unavailable",blockers:Object.freeze([TRANSPORT_BLOCKER,...t?[]:[JWKS_BLOCKER]])};if(!t)return{status:"unavailable",blockers:Object.freeze([JWKS_BLOCKER])};const a=runtimeMethods(),o=e.attemptPorts??runtimeMessageAttemptPorts(n,n.configuredServiceUrl);return{status:"ready",blockers:[],capabilityBlockers:CAPABILITY_BLOCKERS,serviceMethods:a,factory:new MsRuntimeMessageChannelConsumerFactory({client:n.messageClient,verifier:t,ports:o,journal:e.commandJournal,allowedMethods:new Set(a),options:{poisonJournal:e.poisonJournal,...e.onConsumerDeliveryError?{onDeliveryError:e.onConsumerDeliveryError}:{},...e.onConsumerLeaseStarvation?{onLeaseStarvation:e.onConsumerLeaseStarvation}:{},...e.onConsumerRequestTerminalAccepted?{onRequestTerminalAccepted:e.onConsumerRequestTerminalAccepted}:{},...e.onConsumerRequestAcknowledged?{onRequestAcknowledged:e.onConsumerRequestAcknowledged}:{},...e.onConsumerRequestFailure?{onRequestFailure:e.onConsumerRequestFailure}:{}}}),...void 0===e.attemptPorts?{resourceBindingContractRevision:RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION}:{}}}function startGatewayGrantJwks(e,r,t){const n=grantAdapterOptions.get(e);if(!n)throw new Error("untrusted Gateway grant readiness adapter");const a=n.gateway.baseUrl.toString().replace(/\/+$/,""),o=r?createCloudGrantVerifier(a):new GatewayGrantJwksVerifier(new RuntimeJwksVerifier(`${a}/.well-known/runtime-execution-grant-jwks.json`));return warmGrantJwks(o,{onRetry:({attempt:e,error:r})=>t?.({ready:!1,attempt:e,error:r})}).then(e=>t?.({ready:e})),o}export function runtimeMessageAttemptPorts(e,r){return{async resolve({request:t,command:n,executionGrant:a,getLease:o,journalStoreId:s,journalGeneration:i,journalRecord:c,abortSignal:u}){const d="resourceBindings"in t?t.resourceBindings:void 0,l="resourceBindingContractRevision"in t?t.resourceBindingContractRevision:void 0,m="skills.install"===n.name||"agent.applyTemplate"===n.name?n.params.artifact:void 0,p="mcp.prepare"===n.name||"mcp.set"===n.name?n.params.definition:void 0;if((m||p)&&(l!==RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION||!d))throw new RuntimeResourceResolutionError("resolution_rejected","resource-bound Service delivery requires the Types 4.1 binding carrier",void 0,`binding_contract_revision=${l??"absent"} bindings=${d?"present":"absent"}`);const R=new HttpRuntimeOperationResourceResolver({gateway:e.gateway,operationId:t.operationId,requestMessageId:t.requestMessageId,instanceId:t.instanceId,paramsHash:t.paramsHash,bindings:d??[],getAuthorization:()=>{const e=o();return{executionGrant:a,runtimeLeaseCredential:e.runtimeLeaseCredential,fence:deliveryFence(t,e,s,i)}},parseSkillArtifact:e=>parseSkillPackage(e),signal:u});if("prepared"!==c.phase&&"started"!==c.phase||(m&&await R.readVerifiedArtifact(m),p&&await R.resolveMcpDefinition(p)),"session.setModel"===n.name){if(!e.messageService)throw new Error("Cloud runtime cannot project a personal session model");const n=e.scopedDeliveryKey;if(!n)throw new Error("session model requires X-Runtime-Delivery-Key");return{resources:R,sessionModelProjection:{project:async({conversationId:e,modelOverrideId:a})=>{const s=o(),i=new MessageServiceSessionModelHttpAuthority({messageServiceUrl:r,scopedDeliveryKey:n,fetchAuthorized:(e,r)=>fetchRuntimeLeaseAttempt(e,r??{})});return await i.project({conversationId:e,operationId:t.operationId,requestMessageId:t.requestMessageId,requestHash:t.requestHash,modelOverrideId:a,runtimeLeaseCredential:s.runtimeLeaseCredential})}}}}if("session.clear"!==n.name)return{resources:R};if(!e.messageService)throw new Error("Cloud runtime cannot access personal conversation history");n.context.conversation;const v=o(),C=new MessageServiceConversationClearHttpAuthority({messageServiceUrl:r,runtimeLeaseCredential:v.runtimeLeaseCredential,fetchAuthorized:(e,r)=>fetchRuntimeLeaseAttempt(e,r??{})});return{resources:R,historyBoundary:new MessageServiceConversationHistoryBoundary({operationId:t.operationId,requestMessageId:t.requestMessageId,requestHash:t.requestHash,fence:deliveryFence(t,v,s,i),authority:C})}}}}function runtimeMethods(){return[...intersectRuntimeServiceMethodsWithBackendCapabilities(RUNTIME_PARITY_MANIFEST.filter(e=>"ready"===e.status).map(e=>e.method))]}function contractArtifactRequirement(){try{return runtimeServiceContractRequirement()}catch{return CONTRACT_ARTIFACT_BLOCKER.requiredContract}}function parseSkillPackage(e){try{return parseAndValidateTemplatePackage(Buffer.from(e))}catch(r){if(!(r instanceof TemplatePackageError))throw r;throw new RuntimeResourceResolutionError("resolution_rejected","skill package failed validation",void 0,`package_invalid bytes=${e.byteLength} reason=${r.message}`)}}function deliveryFence(e,r,t,n){if(r.handlerIdentity!==e.runtimeHandlerIdentity||r.runtimeEpoch!==e.dispatchEpoch)throw new Error("runtime delivery fence does not match the retained request");return{claimId:e.requestMessageId,handlerIdentity:r.handlerIdentity,runtimeEpoch:r.runtimeEpoch,fencingToken:r.runtimeEpoch,journalStoreId:t,journalGeneration:n}}
|