beeos-claw 0.6.66-cloud.2 → 0.6.66-cloud.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -13
- 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-gateway/local-session-history.js +1 -1
- package/dist/acp-gateway/mcp-desired-state-controller.js +1 -1
- package/dist/acp-gateway/mcp-desired-state-store.js +1 -1
- package/dist/acp-gateway/mcp-service.js +1 -1
- package/dist/acp-server.js +1 -1
- package/dist/agent-sync.js +1 -1
- package/dist/approval/gate.js +1 -0
- package/dist/approval/journal.js +1 -0
- package/dist/approval/presentation.js +1 -0
- package/dist/approval/protocol.generated.js +1 -0
- package/dist/approval/turn-policy.js +1 -0
- package/dist/auto-reply-tokens.js +1 -1
- package/dist/automation/tools.js +1 -1
- package/dist/canvas/relay-client.js +1 -1
- package/dist/canvas/static-html.js +1 -0
- package/dist/canvas/tools.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/gateway-client.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/message-projection-inbound-consumer.js +1 -1
- package/dist/plugin-registration-plan.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/deepseek-reasoning-stream.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-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-runtime-capabilities.js +1 -1
- package/dist/runtime/openclaw-session-model.js +1 -0
- package/dist/runtime/openclaw-session-write-quiescence.js +1 -1
- package/dist/runtime/reply-router.js +1 -1
- package/dist/runtime/runtime-command-dispatcher.js +1 -1
- package/dist/runtime/runtime-command-journal.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-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/session-new-runtime-delivery-bridge.js +1 -1
- package/dist/runtime/session-set-model-mapping.js +1 -1
- package/dist/runtime/write-runtime-failure.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/native-output-tool-hook.js +1 -0
- 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 +7 -2
- package/package.json +11 -11
- package/runtime-service-wire-identity.v1.json +12 -12
- package/scripts/runtime-blackbox-worker-main.mjs +5 -2
- package/dist/agent-auth.js +0 -1
- package/dist/bridge-discovery.js +0 -1
- package/dist/contracts/question/codec.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/message-service-session-reasoning-http-authority.js +0 -1
- package/dist/runtime/openclaw-native-sessions.js +0 -1
- package/dist/runtime/openclaw-question-adapter.js +0 -1
- package/dist/runtime/openclaw-title-provider.js +0 -1
- package/dist/runtime/question-wire.js +0 -1
- package/dist/runtime/requested-model.js +0 -1
- package/dist/runtime/runtime-jwks-verifier.js +0 -1
- package/dist/runtime/runtime-reasoning.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{createHash,randomUUID}from"node:crypto";import{readFile}from"node:fs/promises";import{canonicalizeJcs}from"@beeos-ai/beeos-types/runtime";import{createRuntimeAppendTimingRecorder}from"./runtime-append-timing.js";import{OwnedDirectoryLockContendedError,withOwnedDirectoryLock}from"./owned-directory-lock.js";import{MonotonicJournalSegments}from"./monotonic-journal-segments.js";const HASH_ONLY_RESULT_COMMANDS=new Set(["session.load","session.history","session.list","agent.listProjection","skills.list","models.list","cron.list","cron.status","cron.runs","mcp.list","terminal.ping","terminal.wait"]),SAFE_CANONICAL_RESULT_COMMANDS=new Set(["session.clear","session.setMode","session.setModel","session.setReasoning","session.cancel","skills.install","skills.uninstall","skills.setEnabled","cron.remove","mcp.prepare","mcp.set","mcp.unset","terminal.input","terminal.resize","terminal.close","terminal.release","terminal.kill","canvas.toggle","canvas.clear","canvas.reference","canvas.dimensions"]);export const runtimeCommandResultPersistencePolicy=e=>SAFE_CANONICAL_RESULT_COMMANDS.has(e)?"canonical_result":"hash_only";export const runtimeCommandIsReplayableQuery=e=>HASH_ONLY_RESULT_COMMANDS.has(e);export const runtimeCommandResultHash=e=>createHash("sha256").update(canonicalizeJcs(e)).digest("hex");const emptyDocument=()=>({version:2,lineage:{journalStoreId:randomUUID(),journalGeneration:"1"},records:[],cancellations:[]}),CHECKPOINT_INTERVAL_MS=6e5,CHECKPOINT_DELTA_COUNT=512,CHECKPOINT_DELTA_BYTES=8388608,CHECKPOINT_FOREGROUND_QUIET_MS=50;export class RuntimeCommandJournalConflictError extends Error{constructor(e){super(e),this.name="RuntimeCommandJournalConflictError"}}export class FileRuntimeCommandJournal{file;retentionMs;now;publication;segments;maintenance;forceCheckpointRequested=!1;maintenanceDue;maintenanceDueAtMs;prunePending=!1;foregroundUpdates=0;foregroundRevision=0;constructor(e,t=6048e5,n=Date.now,o={}){this.file=e,this.retentionMs=t,this.now=n,this.publication=o,this.segments=new MonotonicJournalSegments(e)}async lineage(){return await this.update(e=>({...e.lineage}))}async advanceLineageGeneration(e){return await this.update(t=>{if(t.lineage.journalStoreId!==e.journalStoreId)throw new RuntimeCommandJournalConflictError("journal store changed during incarnation advance");const n=BigInt(t.lineage.journalGeneration),o=BigInt(e.floor),r=(n>o?n:o)+1n;if(r>9223372036854775807n)throw new RuntimeCommandJournalConflictError("journal generation overflow");return t.lineage={journalStoreId:t.lineage.journalStoreId,journalGeneration:String(r)},{...t.lineage}})}async get(e){return(await this.read()).records.find(t=>t.operationId===e)??null}async getCancellation(e){return(await this.read()).cancellations.find(t=>t.operationId===e)??null}async listMcpLiveReleases(){const e=await this.read();return Object.freeze(e.records.flatMap(e=>e.mcpLiveRelease?[e.mcpLiveRelease]:[]))}async listMcpActiveDesiredStates(){const e=await this.read();return Object.freeze(e.records.flatMap(e=>e.mcpActiveDesiredState?[e.mcpActiveDesiredState]:[]))}async recordMcpDesiredStateCommit(e){const t=normalizeMcpDesiredStateCommit(e);return await this.update(e=>{const n=e.records.findIndex(e=>e.operationId===t.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("MCP desired state has no command record");const o=e.records[n];if(assertMcpCommitBindsRecord(t,o),"started"!==o.phase){if(sameMcpDesiredStateCommit(o.mcpDesiredStateCommit,t))return o;throw new RuntimeCommandJournalConflictError("MCP desired state commit crossed its journal boundary")}if(o.mcpDesiredStateCommit){if(sameMcpDesiredStateCommit(o.mcpDesiredStateCommit,t))return o;throw new RuntimeCommandJournalConflictError("MCP desired state commit conflicts with journal")}const r={...o,mcpDesiredStateCommit:t,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString()};return e.records[n]=r,r})}async releaseMcpLiveEffect(e){return await this.update(t=>{const n=t.records.findIndex(t=>t.operationId===e.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("MCP release has no command record");const o=t.records[n];if("effect_committed"!==o.phase&&"projection_committed"!==o.phase)throw new RuntimeCommandJournalConflictError("MCP release requires a committed effect");if(!o.mcpDesiredStateCommit)throw new RuntimeCommandJournalConflictError("MCP release lacks a durable desired-state commit");if("service"===e.source&&!o.messageBinding)throw new RuntimeCommandJournalConflictError("Service MCP release lacks a Message Service request binding");const r=releaseFromCommit(o.mcpDesiredStateCommit,e,new Date(this.now()).toISOString());if(o.mcpLiveRelease){if(sameMcpLiveRelease(o.mcpLiveRelease,r))return o;throw new RuntimeCommandJournalConflictError("MCP release conflicts with journal")}const i={...o,mcpLiveRelease:r,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString()};return t.records[n]=i,i})}async promoteMcpDesiredStateActive(e){return await this.update(t=>{const n=t.records.findIndex(t=>t.operationId===e.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("MCP active promotion has no command record");const o=t.records[n],r=activeFromRelease(o.mcpLiveRelease,e,new Date(this.now()).toISOString());if(o.mcpActiveDesiredState){if(sameMcpActiveDesiredState(o.mcpActiveDesiredState,r))return o;throw new RuntimeCommandJournalConflictError("MCP active desired state conflicts with journal")}const i={...o,mcpActiveDesiredState:r,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString()};return t.records[n]=i,i})}async acceptMessageRequest(e){return await this.update(t=>{let n=t.records.find(t=>t.operationId===e.operationId);if(n||(n={operationId:e.operationId,command:e.command,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,phase:"prepared",revision:1,updatedAt:new Date(this.now()).toISOString()},t.records.push(n)),n.command!==e.command||n.paramsHash!==e.paramsHash||n.runtimeEpoch!==e.runtimeEpoch)throw new RuntimeCommandJournalConflictError("message request conflicts with command journal");const o={requestMessageId:e.requestMessageId,requestHash:e.requestHash,acceptedAt:new Date(this.now()).toISOString()};if(n.messageBinding&&(n.messageBinding.requestMessageId!==o.requestMessageId||n.messageBinding.requestHash!==o.requestHash))throw new RuntimeCommandJournalConflictError("operation reused by a different message request");return n.messageBinding??=o,n})}async observeCancellation(e){return await this.update(t=>{const n=t.cancellations.find(t=>t.eventId===e.eventId);if(n){if(n.operationId!==e.operationId||n.requestMessageId!==e.requestMessageId||n.requestHash!==e.requestHash)throw new RuntimeCommandJournalConflictError("operation cancellation observation conflict");return n}const o=t.cancellations.find(t=>t.operationId===e.operationId);if(o&&(o.requestMessageId!==e.requestMessageId||o.requestHash!==e.requestHash))throw new RuntimeCommandJournalConflictError("operation cancellation request correlation conflict");const r={...e,observedAt:new Date(this.now()).toISOString()};return t.cancellations.push(r),r})}async prepare(e){return await this.update(t=>{const n=t.records.find(t=>t.operationId===e.operationId);if(n){if(n.command!==e.command||n.paramsHash!==e.paramsHash)throw new RuntimeCommandJournalConflictError("operation identity reused with different command or params hash");if(n.runtimeEpoch!==e.runtimeEpoch)throw new RuntimeCommandJournalConflictError("operation belongs to a different runtime epoch");return n}const o={...e,phase:"prepared",revision:1,updatedAt:new Date(this.now()).toISOString()};return t.records.push(o),o})}async transition(e){return await this.update(t=>{const n=t.records.findIndex(t=>t.operationId===e.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("operation was not prepared");const o=t.records[n];if(o.revision!==e.expectedRevision)throw new RuntimeCommandJournalConflictError("journal revision conflict");const r="effect_committed"===o.phase&&"effect_committed"===e.phase&&void 0!==e.agentProjection&&void 0===o.agentProjectionIntent&&"pending"===o.agentProjectionPreparationFailure?.state;if("projection_committed"===o.phase||"failed"===o.phase||"outcome_unknown"===o.phase||"effect_committed"===o.phase&&"projection_committed"!==e.phase&&!r)throw new RuntimeCommandJournalConflictError("terminal journal record is immutable");if(void 0!==e.projectionSnapshot&&"projection_committed"!==e.phase)throw new RuntimeCommandJournalConflictError("projection receipt requires projection_committed phase");if(void 0!==e.agentProjection&&"effect_committed"!==e.phase)throw new RuntimeCommandJournalConflictError("agent projection intent requires effect_committed phase");const i=void 0===e.agentProjection?void 0:normalizeAgentProjectionPreparation(e.agentProjection,o);if(r&&i&&!sameProjectionPreparationBase(o.agentProjectionPreparationFailure,i))throw new RuntimeCommandJournalConflictError("agent projection preparation conflicts with committed operation");const{agentProjectionIntent:a,agentProjectionPreparationFailure:s,...c}=o,d={...void 0===i?o:c,phase:e.phase,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString(),...void 0===e.result?{}:persistedResult(o.command,e.result),...void 0===e.projectionSnapshot?{}:{projectionReceipt:projectionReceipt(e.projectionSnapshot)},...void 0===i?{}:isAgentProjectionIntent(i)?{agentProjectionIntent:i}:{agentProjectionPreparationFailure:i},...void 0===e.errorCode?{}:{errorCode:e.errorCode}};return t.records[n]=d,d})}async recordAgentProjectionIntent(e){return await this.update(t=>{const n=t.records.findIndex(t=>t.operationId===e.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("operation was not prepared");const o=t.records[n];if(o.revision!==e.expectedRevision||"effect_committed"!==o.phase)throw new RuntimeCommandJournalConflictError("projection intent cannot mutate this command journal record");const r=normalizeAgentProjectionIntent(e.intent,o);if(o.agentProjectionIntent){if(canonicalizeJcs(o.agentProjectionIntent)!==canonicalizeJcs(r))throw new RuntimeCommandJournalConflictError("agent projection intent conflicts with committed operation");return o}if("pending"!==o.agentProjectionPreparationFailure?.state||!sameProjectionPreparationBase(o.agentProjectionPreparationFailure,r))throw new RuntimeCommandJournalConflictError("projection intent requires matching retryable preparation failure");const{agentProjectionPreparationFailure:i,...a}=o,s={...a,agentProjectionIntent:r,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString()};return t.records[n]=s,s})}async recordAgentProjectionBlocked(e){return await this.update(t=>{const n=t.records.findIndex(t=>t.operationId===e.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("operation was not prepared");const o=t.records[n];if(o.revision!==e.expectedRevision||"effect_committed"!==o.phase||!o.agentProjectionIntent||o.agentProjectionIntent.projectionRevision!==e.revision)throw new RuntimeCommandJournalConflictError("blocked projection cannot mutate this command journal record");if(o.agentProjectionTerminal){if("blocked"===o.agentProjectionTerminal.state&&o.agentProjectionTerminal.revision===e.revision)return o;throw new RuntimeCommandJournalConflictError("agent projection terminal conflicts with committed operation")}const r=agentProjectionTerminalReceipt(e.revision),i={...o,agentProjectionTerminal:r,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString()};return t.records[n]=i,i})}async compact(){return this.maintenance?await this.maintenance:!1===this.maintenanceDue&&!this.prunePending&&void 0!==this.maintenanceDueAtMs&&Date.now()<this.maintenanceDueAtMs?0:await this.startMaintenance()}async checkpoint(){return this.forceCheckpointRequested=!0,await this.startMaintenance()}async read(){return(await this.readState()).document}async readState(){const e=await this.readLegacy(),t=new Map;if(e){t.set("meta:lineage",{value:e.lineage,logicalRevision:e.lineage.journalGeneration,publisherEpoch:"0"});for(const n of e.records)t.set(`record:${n.operationId}`,{value:n,logicalRevision:String(n.revision),publisherEpoch:"0"});for(const n of e.cancellations)t.set(`cancellation:${n.eventId}`,{value:n,logicalRevision:"1",publisherEpoch:"0"})}const n=await this.segments.readState(t),o=n.values,r=o.get("meta:lineage")?.value;return{document:{version:2,lineage:r??emptyDocument().lineage,records:[...o.entries()].filter(([e])=>e.startsWith("record:")).map(([,e])=>validateRecordReceipts(migrateLegacyCommittedPhase(e.value))),cancellations:[...o.entries()].filter(([e])=>e.startsWith("cancellation:")).map(([,e])=>e.value)},authorityFloor:n.authorityFloor,checkpointAtMs:n.checkpointAtMs,deltaCount:n.deltaCount,deltaBytes:n.deltaBytes,oldestDeltaAtMs:n.oldestDeltaAtMs,hasDurableLineage:o.has("meta:lineage")&&n.hasDurableState}}async readLegacy(){try{const e=JSON.parse(await readFile(this.file,"utf8"));if(!Array.isArray(e.records))throw new Error("unsupported command journal");const t=e.records.map(e=>validateRecordReceipts(migrateLegacyCommittedPhase(e)));if(1===e.version)return{...emptyDocument(),records:t};if(2!==e.version||!e.lineage?.journalStoreId||!/^[1-9][0-9]*$/.test(e.lineage.journalGeneration))throw new Error("unsupported command journal");return{...e,records:t,cancellations:Array.isArray(e.cancellations)?e.cancellations:[]}}catch(e){if("ENOENT"===e.code)return null;throw e}}async update(e){const t=createRuntimeAppendTimingRecorder("journal.update",{file:this.file});let n=!1;this.foregroundUpdates+=1;try{return await withOwnedDirectoryLock(`${this.file}.lock`,async o=>{t.mark("lock");const r=await this.readState();t.mark("read");const i=r.document,a=structuredClone(i),s=e(i),c=[];if(r.hasDurableLineage&&sameValue(a.lineage,i.lineage)||c.push({key:"meta:lineage",logicalRevision:i.lineage.journalGeneration,value:i.lineage}),diffValues(a.records,i.records,e=>e.operationId,e=>String(e.revision),"record:",c),diffValues(a.cancellations,i.cancellations,e=>e.eventId,()=>"1","cancellation:",c),0===c.length)return t.mark("noop"),s;await(this.publication.beforePublish?.(o.epoch)),t.mark("before-publish"),await o.assertOwned(),t.mark("assert-owned");const d=await this.segments.publishDelta(o.epoch,c,r.authorityFloor);t.mark("publish-delta");const m=Date.now();return this.maintenanceDueAtMs=checkpointDueAt(r,1,d,m),n=this.maintenanceDueAtMs<=m,this.maintenanceDue=n,s},{...this.publication.lockOptions,epochFloor:()=>this.segments.authorityFloor()})}finally{this.foregroundUpdates-=1,this.foregroundRevision+=1,t.finish(),n&&this.scheduleMaintenance()}}scheduleMaintenance(){this.startMaintenance().catch(e=>{try{this.publication.onMaintenanceError?this.publication.onMaintenanceError(e):emitMaintenanceWarning(e)}catch(e){emitMaintenanceWarning(e)}})}startMaintenance(){if(this.maintenance)return this.maintenance;const e=(async()=>{let e=0,t=!1;do{let n=this.forceCheckpointRequested;this.forceCheckpointRequested=!1,n||(await this.waitForForegroundQuiet(),n=this.forceCheckpointRequested,this.forceCheckpointRequested=!1);const o=await this.runMaintenance(n);e+=o.removed,t=o.contended}while(this.forceCheckpointRequested||t);return e})().finally(()=>{this.maintenance===e&&(this.maintenance=void 0)});return this.maintenance=e,e}async waitForForegroundQuiet(){for(;;){if(this.forceCheckpointRequested)return;const e=this.foregroundRevision;if(0===this.foregroundUpdates){if(await new Promise(e=>setTimeout(e,50)),this.forceCheckpointRequested||0===this.foregroundUpdates&&this.foregroundRevision===e)return}else await new Promise(e=>setTimeout(e,50))}}async runMaintenance(e){const t=createRuntimeAppendTimingRecorder("journal.checkpoint",{file:this.file});try{if(!e&&this.prunePending)return await this.segments.prune(),this.prunePending=!1,t.mark("prune-pending"),{removed:0,contended:!1};let n=!1;const o=await withOwnedDirectoryLock(`${this.file}.lock`,async o=>{t.mark("lock");const r=await this.readState();if(t.mark("read"),!e&&!checkpointDue(r))return this.maintenanceDue=!1,this.maintenanceDueAtMs=checkpointDueAt(r),t.mark("not-due"),0;const i=r.document,a=this.now()-this.retentionMs,s=i.records.length;i.records=i.records.filter(e=>"prepared"===e.phase||"started"===e.phase||Date.parse(e.updatedAt)>=a);const c=i.cancellations.length;i.cancellations=i.cancellations.filter(e=>Date.parse(e.observedAt)>=a);const d=s-i.records.length+c-i.cancellations.length,m=documentValues(i);return await(this.publication.beforePublish?.(o.epoch)),t.mark("before-publish"),await o.assertOwned(),t.mark("assert-owned"),await this.segments.checkpointSnapshot(o.epoch,m,r.authorityFloor),t.mark("publish-snapshot"),this.maintenanceDue=!1,this.maintenanceDueAtMs=Number.POSITIVE_INFINITY,this.prunePending=!0,n=!0,d},{...this.publication.lockOptions,failIfContended:!e,epochFloor:()=>this.segments.authorityFloor()});return t.mark("lock-released"),n&&(await this.segments.prune(),this.prunePending=!1,t.mark("prune")),{removed:o,contended:!1}}catch(n){if(!e&&n instanceof OwnedDirectoryLockContendedError)return t.mark("deferred-busy"),{removed:0,contended:!0};throw n}finally{t.finish(e?"forced":"scheduled")}}}function checkpointDue(e,t=0,n=0,o=Date.now()){return checkpointDueAt(e,t,n,o)<=o}function checkpointDueAt(e,t=0,n=0,o=Date.now()){const r=e.deltaCount+t,i=e.deltaBytes+n,a=e.oldestDeltaAtMs||(t>0?o:0),s=e.checkpointAtMs||a;return r>=512||i>=8388608?o:r>0&&s>0?s+6e5:Number.POSITIVE_INFINITY}function emitMaintenanceWarning(e){process.emitWarning(e instanceof Error?e.message:String(e),{code:"BEEOS_RUNTIME_JOURNAL_CHECKPOINT_FAILED"})}function diffValues(e,t,n,o,r,i){const a=new Map(e.map(e=>[n(e),e])),s=new Map(t.map(e=>[n(e),e]));for(const[e,t]of s){const n=a.get(e);void 0!==n&&sameValue(n,t)||i.push({key:`${r}${e}`,logicalRevision:o(t),value:t})}for(const[e,t]of a)s.has(e)||i.push({key:`${r}${e}`,logicalRevision:o(t),tombstone:!0})}function documentValues(e){return[{key:"meta:lineage",logicalRevision:e.lineage.journalGeneration,value:e.lineage},...e.records.map(e=>({key:`record:${e.operationId}`,logicalRevision:String(e.revision),value:e})),...e.cancellations.map(e=>({key:`cancellation:${e.eventId}`,logicalRevision:"1",value:e}))]}function sameValue(e,t){return canonicalizeJcs(e)===canonicalizeJcs(t)}function migrateLegacyCommittedPhase(e){return{...e,phase:"committed"===e.phase?"effect_committed":e.phase}}export class InMemoryRuntimeCommandJournal{records=new Map;cancellations=new Map;async get(e){return this.records.get(e)??null}async getCancellation(e){return[...this.cancellations.values()].find(t=>t.operationId===e)??null}async listMcpLiveReleases(){return Object.freeze([...this.records.values()].flatMap(e=>e.mcpLiveRelease?[e.mcpLiveRelease]:[]))}async listMcpActiveDesiredStates(){return Object.freeze([...this.records.values()].flatMap(e=>e.mcpActiveDesiredState?[e.mcpActiveDesiredState]:[]))}async recordMcpDesiredStateCommit(e){const t=normalizeMcpDesiredStateCommit(e),n=this.records.get(t.operationId);if(!n)throw new RuntimeCommandJournalConflictError("MCP desired state has no command record");if(assertMcpCommitBindsRecord(t,n),"started"!==n.phase){if(sameMcpDesiredStateCommit(n.mcpDesiredStateCommit,t))return n;throw new RuntimeCommandJournalConflictError("MCP desired state commit crossed its journal boundary")}if(n.mcpDesiredStateCommit){if(sameMcpDesiredStateCommit(n.mcpDesiredStateCommit,t))return n;throw new RuntimeCommandJournalConflictError("MCP desired state commit conflicts with journal")}const o={...n,mcpDesiredStateCommit:t,revision:n.revision+1,updatedAt:(new Date).toISOString()};return this.records.set(t.operationId,o),o}async releaseMcpLiveEffect(e){const t=this.records.get(e.operationId);if(!t)throw new RuntimeCommandJournalConflictError("MCP release has no command record");if("effect_committed"!==t.phase&&"projection_committed"!==t.phase)throw new RuntimeCommandJournalConflictError("MCP release requires a committed effect");if(!t.mcpDesiredStateCommit)throw new RuntimeCommandJournalConflictError("MCP release lacks a durable desired-state commit");if("service"===e.source&&!t.messageBinding)throw new RuntimeCommandJournalConflictError("Service MCP release lacks a Message Service request binding");const n=releaseFromCommit(t.mcpDesiredStateCommit,e,(new Date).toISOString());if(t.mcpLiveRelease){if(sameMcpLiveRelease(t.mcpLiveRelease,n))return t;throw new RuntimeCommandJournalConflictError("MCP release conflicts with journal")}const o={...t,mcpLiveRelease:n,revision:t.revision+1,updatedAt:(new Date).toISOString()};return this.records.set(e.operationId,o),o}async promoteMcpDesiredStateActive(e){const t=this.records.get(e.operationId);if(!t)throw new RuntimeCommandJournalConflictError("MCP active promotion has no command record");const n=activeFromRelease(t.mcpLiveRelease,e,(new Date).toISOString());if(t.mcpActiveDesiredState){if(sameMcpActiveDesiredState(t.mcpActiveDesiredState,n))return t;throw new RuntimeCommandJournalConflictError("MCP active desired state conflicts with journal")}const o={...t,mcpActiveDesiredState:n,revision:t.revision+1,updatedAt:(new Date).toISOString()};return this.records.set(e.operationId,o),o}async acceptMessageRequest(e){let t=this.records.get(e.operationId);if(t||(t={operationId:e.operationId,command:e.command,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,phase:"prepared",revision:1,updatedAt:(new Date).toISOString()},this.records.set(e.operationId,t)),t.command!==e.command||t.paramsHash!==e.paramsHash||t.runtimeEpoch!==e.runtimeEpoch||t.messageBinding&&(t.messageBinding.requestMessageId!==e.requestMessageId||t.messageBinding.requestHash!==e.requestHash))throw new RuntimeCommandJournalConflictError("message request conflicts with command journal");return t.messageBinding??={requestMessageId:e.requestMessageId,requestHash:e.requestHash,acceptedAt:(new Date).toISOString()},t}async observeCancellation(e){const t=this.cancellations.get(e.eventId);if(t){if(t.operationId!==e.operationId||t.requestMessageId!==e.requestMessageId||t.requestHash!==e.requestHash)throw new RuntimeCommandJournalConflictError("operation cancellation observation conflict");return t}const n=[...this.cancellations.values()].find(t=>t.operationId===e.operationId);if(n&&(n.requestMessageId!==e.requestMessageId||n.requestHash!==e.requestHash))throw new RuntimeCommandJournalConflictError("operation cancellation request correlation conflict");const o={...e,observedAt:(new Date).toISOString()};return this.cancellations.set(e.eventId,o),o}async prepare(e){const t=this.records.get(e.operationId);if(t){if(t.command!==e.command||t.paramsHash!==e.paramsHash||t.runtimeEpoch!==e.runtimeEpoch)throw new RuntimeCommandJournalConflictError("operation identity conflict");return t}const n={...e,phase:"prepared",revision:1,updatedAt:(new Date).toISOString()};return this.records.set(e.operationId,n),n}async transition(e){const t=this.records.get(e.operationId);if(!t||t.revision!==e.expectedRevision)throw new RuntimeCommandJournalConflictError("revision conflict");const n="effect_committed"===t.phase&&"effect_committed"===e.phase&&void 0!==e.agentProjection&&void 0===t.agentProjectionIntent&&"pending"===t.agentProjectionPreparationFailure?.state;if("projection_committed"===t.phase||"failed"===t.phase||"outcome_unknown"===t.phase||"effect_committed"===t.phase&&"projection_committed"!==e.phase&&!n)throw new RuntimeCommandJournalConflictError("terminal journal record is immutable");if(void 0!==e.projectionSnapshot&&"projection_committed"!==e.phase)throw new RuntimeCommandJournalConflictError("projection receipt requires projection_committed phase");if(void 0!==e.agentProjection&&"effect_committed"!==e.phase)throw new RuntimeCommandJournalConflictError("agent projection intent requires effect_committed phase");const o=void 0===e.agentProjection?void 0:normalizeAgentProjectionPreparation(e.agentProjection,t);if(n&&o&&!sameProjectionPreparationBase(t.agentProjectionPreparationFailure,o))throw new RuntimeCommandJournalConflictError("agent projection preparation conflicts with committed operation");const{agentProjectionIntent:r,agentProjectionPreparationFailure:i,...a}=t,s={...void 0===o?t:a,phase:e.phase,revision:t.revision+1,updatedAt:(new Date).toISOString(),...void 0===e.result?{}:persistedResult(t.command,e.result),...void 0===e.projectionSnapshot?{}:{projectionReceipt:projectionReceipt(e.projectionSnapshot)},...void 0===o?{}:isAgentProjectionIntent(o)?{agentProjectionIntent:o}:{agentProjectionPreparationFailure:o},...void 0===e.errorCode?{}:{errorCode:e.errorCode}};return this.records.set(e.operationId,s),s}async recordAgentProjectionIntent(e){const t=this.records.get(e.operationId);if(!t||t.revision!==e.expectedRevision||"effect_committed"!==t.phase)throw new RuntimeCommandJournalConflictError("projection intent cannot mutate this command journal record");const n=normalizeAgentProjectionIntent(e.intent,t);if(t.agentProjectionIntent){if(canonicalizeJcs(t.agentProjectionIntent)!==canonicalizeJcs(n))throw new RuntimeCommandJournalConflictError("agent projection intent conflicts with committed operation");return t}if("pending"!==t.agentProjectionPreparationFailure?.state||!sameProjectionPreparationBase(t.agentProjectionPreparationFailure,n))throw new RuntimeCommandJournalConflictError("projection intent requires matching retryable preparation failure");const{agentProjectionPreparationFailure:o,...r}=t,i={...r,agentProjectionIntent:n,revision:t.revision+1,updatedAt:(new Date).toISOString()};return this.records.set(e.operationId,i),i}async recordAgentProjectionBlocked(e){const t=this.records.get(e.operationId);if(!t||t.revision!==e.expectedRevision||"effect_committed"!==t.phase||!t.agentProjectionIntent||t.agentProjectionIntent.projectionRevision!==e.revision)throw new RuntimeCommandJournalConflictError("blocked projection cannot mutate this command journal record");if(t.agentProjectionTerminal){if("blocked"===t.agentProjectionTerminal.state&&t.agentProjectionTerminal.revision===e.revision)return t;throw new RuntimeCommandJournalConflictError("agent projection terminal conflicts with committed operation")}const n={...t,agentProjectionTerminal:agentProjectionTerminalReceipt(e.revision),revision:t.revision+1,updatedAt:(new Date).toISOString()};return this.records.set(e.operationId,n),n}async compact(){return 0}async checkpoint(){return 0}}function persistedResult(e,t){return"canonical_result"===runtimeCommandResultPersistencePolicy(e)?{result:t}:{resultReceipt:{policy:"hash_only",resultHash:runtimeCommandResultHash(t),redacted:{kind:runtimeCommandIsReplayableQuery(e)?"query_result":"mutation_result",command:e}}}}function projectionReceipt(e){if("synced"!==e.state||!/^(0|[1-9][0-9]*)$/.test(e.revision))throw new Error("invalid projection revision");if(void 0!==e.platformAgentId&&!/^[a-zA-Z0-9._:-]{1,256}$/.test(e.platformAgentId))throw new Error("invalid projection platform agent id");const t=void 0===e.mcpReceipt?void 0:normalizeMcpProjectionReceipt(e.mcpReceipt),n=Object.freeze({revision:e.revision,state:"synced",..."string"==typeof e.platformAgentId&&e.platformAgentId?{platformAgentId:e.platformAgentId}:{},...t?{mcpReceipt:t}:{}});return Object.freeze({schemaVersion:1,revision:n.revision,snapshot:n,snapshotHash:runtimeCommandResultHash(n)})}function validateRecordReceipts(e){if(void 0!==e.agentProjectionIntent&&void 0!==e.agentProjectionPreparationFailure)throw new Error("agent projection journal record is ambiguous");const t=void 0!==e.agentProjectionIntent?{...e,agentProjectionIntent:normalizeAgentProjectionIntent(e.agentProjectionIntent,e)}:void 0!==e.agentProjectionPreparationFailure?{...e,agentProjectionPreparationFailure:normalizeAgentProjectionPreparation(e.agentProjectionPreparationFailure,e)}:e,n=void 0===t.agentProjectionTerminal?t:{...t,agentProjectionTerminal:normalizeAgentProjectionTerminal(t.agentProjectionTerminal)};if(n.agentProjectionTerminal&&(!n.agentProjectionIntent||"effect_committed"!==n.phase||n.agentProjectionIntent.projectionRevision!==n.agentProjectionTerminal.revision))throw new Error("invalid agent projection terminal receipt");const o=void 0===n.mcpDesiredStateCommit?void 0:normalizeMcpDesiredStateCommit(n.mcpDesiredStateCommit);o&&assertMcpCommitBindsRecord(o,n);const r=void 0===n.mcpLiveRelease?void 0:normalizeMcpLiveRelease(n.mcpLiveRelease);if(r&&(!o||!sameMcpDesiredStateCommit(o,r)||"effect_committed"!==n.phase&&"projection_committed"!==n.phase||"service"===r.source&&!n.messageBinding))throw new Error("invalid MCP live release receipt");const i=void 0===n.mcpActiveDesiredState?void 0:normalizeMcpActiveDesiredState(n.mcpActiveDesiredState);if(i&&(!r||!sameMcpDesiredStateCommit(i,r)||i.effectRecordHash!==r.effectRecordHash||i.releasedAt!==r.releasedAt))throw new Error("invalid MCP active desired-state receipt");const a={...n,...o?{mcpDesiredStateCommit:o}:{},...r?{mcpLiveRelease:r}:{},...i?{mcpActiveDesiredState:i}:{}};if(!a.projectionReceipt)return a;const s=a.projectionReceipt,c=["revision","state",...void 0===s.snapshot?.platformAgentId?[]:["platformAgentId"],...void 0===s.snapshot?.mcpReceipt?[]:["mcpReceipt"]].sort().join(",");if("revision,schemaVersion,snapshot,snapshotHash"!==Object.keys(s).sort().join(",")||Object.keys(s.snapshot??{}).sort().join(",")!==c||"projection_committed"!==a.phase||1!==s.schemaVersion||!/^(0|[1-9][0-9]*)$/.test(s.revision)||"synced"!==s.snapshot?.state||s.snapshot.revision!==s.revision)throw new Error("invalid projection receipt");const d=projectionReceipt(s.snapshot),m=d.snapshot.mcpReceipt;if(m&&(m.operationId!==a.operationId||m.method!==a.command||m.runtimeEpoch!==a.runtimeEpoch))throw new Error("MCP projection receipt does not bind journal operation");if(d.snapshotHash!==s.snapshotHash)throw new Error("invalid projection receipt hash");return{...a,projectionReceipt:d}}function normalizeMcpDesiredStateCommit(e){if(!e||"object"!=typeof e||"desiredStateHash,desiredStateRevision,method,operationId,paramsHash,runtimeEpoch,schemaVersion,server,source"!==Object.keys(e).sort().join(",")||1!==e.schemaVersion||"service"!==e.source&&"acp_local"!==e.source||!safeReceiptIdentifier(e.operationId)||"mcp.set"!==e.method&&"mcp.unset"!==e.method||!isSha256(e.paramsHash)||!/^(0|[1-9][0-9]*)$/.test(e.runtimeEpoch)||!/^(0|[1-9][0-9]*)$/.test(e.desiredStateRevision)||!isSha256(e.desiredStateHash))throw new Error("invalid MCP desired-state commit");return Object.freeze({schemaVersion:1,source:e.source,operationId:e.operationId,method:e.method,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,desiredStateRevision:e.desiredStateRevision,desiredStateHash:e.desiredStateHash,server:normalizeMcpReleaseServer(e.server)})}function normalizeMcpLiveRelease(e){if(!e||"object"!=typeof e)throw new Error("invalid MCP live release receipt");const t=["desiredStateHash","desiredStateRevision","method","operationId","paramsHash","releasedAt","runtimeEpoch","schemaVersion","server","source",..."service"===e.source?["effectRecordHash"]:[]].sort().join(",");if(Object.keys(e).sort().join(",")!==t||"service"===e.source&&!isSha256(e.effectRecordHash)||"acp_local"===e.source&&void 0!==e.effectRecordHash||"string"!=typeof e.releasedAt||!Number.isFinite(Date.parse(e.releasedAt)))throw new Error("invalid MCP live release receipt");const n=normalizeMcpDesiredStateCommit({schemaVersion:e.schemaVersion,source:e.source,operationId:e.operationId,method:e.method,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,desiredStateRevision:e.desiredStateRevision,desiredStateHash:e.desiredStateHash,server:e.server});return Object.freeze({...n,...e.effectRecordHash?{effectRecordHash:e.effectRecordHash}:{},releasedAt:e.releasedAt})}function normalizeMcpActiveDesiredState(e){if(!e||"object"!=typeof e)throw new Error("invalid MCP active desired-state receipt");const t=["activatedAt","desiredStateHash","desiredStateRevision","method","operationId","paramsHash","releasedAt","runtimeEpoch","schemaVersion","server","source",..."service"===e.source?["effectRecordHash","terminalMessageId"]:[]].sort().join(",");if(Object.keys(e).sort().join(",")!==t||"string"!=typeof e.activatedAt||!Number.isFinite(Date.parse(e.activatedAt))||"service"===e.source&&!safeReceiptIdentifier(e.terminalMessageId))throw new Error("invalid MCP active desired-state receipt");const n=normalizeMcpLiveRelease({schemaVersion:e.schemaVersion,source:e.source,operationId:e.operationId,method:e.method,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,desiredStateRevision:e.desiredStateRevision,desiredStateHash:e.desiredStateHash,server:e.server,releasedAt:e.releasedAt,...e.effectRecordHash?{effectRecordHash:e.effectRecordHash}:{}});return Object.freeze({...n,...e.terminalMessageId?{terminalMessageId:e.terminalMessageId}:{},activatedAt:e.activatedAt})}function normalizeMcpReleaseServer(e){const t=e&&"object"==typeof e?Object.keys(e).sort().join(","):"",n=!0===e?.removed;if(!(t===(n?"name,removed":void 0===e?.credentialRef?"definitionRef,definitionSha256,name,version":"credentialRef,definitionRef,definitionSha256,name,version")&&safeReceiptIdentifier(e?.name)&&(n||safeMcpReference(e?.definitionRef)&&safeMcpReference(e?.version)&&isSha256(e?.definitionSha256)&&(void 0===e?.credentialRef||safeMcpReference(e.credentialRef)))))throw new Error("invalid MCP desired-state server identity");return Object.freeze(n?{name:e.name,removed:!0}:{name:e.name,definitionRef:e.definitionRef,version:e.version,definitionSha256:e.definitionSha256,...e.credentialRef?{credentialRef:e.credentialRef}:{}})}function assertMcpCommitBindsRecord(e,t){if(e.operationId!==t.operationId||e.method!==t.command||e.paramsHash!==t.paramsHash||e.runtimeEpoch!==t.runtimeEpoch)throw new RuntimeCommandJournalConflictError("MCP desired-state commit does not bind command journal")}function releaseFromCommit(e,t,n){if(t.operationId!==e.operationId||t.source!==e.source||"service"===t.source&&!isSha256(t.effectRecordHash)||"acp_local"===t.source&&void 0!==t.effectRecordHash)throw new RuntimeCommandJournalConflictError("MCP live release proof does not bind desired state");return Object.freeze({...e,...t.effectRecordHash?{effectRecordHash:t.effectRecordHash}:{},releasedAt:n})}function activeFromRelease(e,t,n){if(!(e&&t.operationId===e.operationId&&t.source===e.source&&Number.isFinite(Date.parse(n))&&("service"!==t.source||isSha256(t.effectRecordHash)&&t.effectRecordHash===e.effectRecordHash&&safeReceiptIdentifier(t.terminalMessageId))&&("acp_local"!==t.source||void 0===t.effectRecordHash&&void 0===t.terminalMessageId)))throw new RuntimeCommandJournalConflictError("MCP active promotion does not bind terminal release proof");return Object.freeze({...e,...t.terminalMessageId?{terminalMessageId:t.terminalMessageId}:{},activatedAt:n})}function sameMcpDesiredStateCommit(e,t){if(!e||!t)return!1;const n=e=>({schemaVersion:e.schemaVersion,source:e.source,operationId:e.operationId,method:e.method,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,desiredStateRevision:e.desiredStateRevision,desiredStateHash:e.desiredStateHash,server:e.server});return canonicalizeJcs(n(e))===canonicalizeJcs(n(t))}function sameMcpLiveRelease(e,t){const n=e=>({...e,releasedAt:""});return canonicalizeJcs(n(e))===canonicalizeJcs(n(t))}function sameMcpActiveDesiredState(e,t){const n=e=>({...e,releasedAt:"",activatedAt:""});return canonicalizeJcs(n(e))===canonicalizeJcs(n(t))}function normalizeMcpProjectionReceipt(e){if(!e||"object"!=typeof e||"desiredStateHash,desiredStateRevision,method,operationId,runtimeEpoch,schemaVersion,server"!==Object.keys(e).sort().join(",")||1!==e.schemaVersion||!safeReceiptIdentifier(e.operationId)||"mcp.set"!==e.method&&"mcp.unset"!==e.method||!/^(0|[1-9][0-9]*)$/.test(e.runtimeEpoch)||!/^(0|[1-9][0-9]*)$/.test(e.desiredStateRevision)||!isSha256(e.desiredStateHash))throw new Error("invalid MCP projection receipt");const t=e.server;if((t&&"object"==typeof t?Object.keys(t).sort().join(","):"")!==(!0===t?.removed?"name,removed":void 0===t?.definitionRef?"name":"definitionRef,definitionSha256,name")||!safeReceiptIdentifier(t?.name)||void 0!==t?.definitionRef&&(!safeReceiptIdentifier(t.definitionRef)||!isSha256(t.definitionSha256)))throw new Error("invalid MCP projection server receipt");return Object.freeze({schemaVersion:1,operationId:e.operationId,method:e.method,runtimeEpoch:e.runtimeEpoch,desiredStateRevision:e.desiredStateRevision,desiredStateHash:e.desiredStateHash,server:Object.freeze(!0===t.removed?{name:t.name,removed:!0}:void 0===t.definitionRef?{name:t.name}:{name:t.name,definitionRef:t.definitionRef,definitionSha256:t.definitionSha256})})}function isSha256(e){return"string"==typeof e&&/^[a-f0-9]{64}$/.test(e)}function safeReceiptIdentifier(e){return"string"==typeof e&&/^[a-zA-Z0-9._:@/-]{1,512}$/.test(e)&&!/(authorization|bearer|credential|secret|token|password|private(?:_|-)?key|headers?|env)/i.test(e)}function safeMcpReference(e){return"string"==typeof e&&/^[a-zA-Z0-9._:@/-]{1,512}$/.test(e)&&!/(authorization|bearer|secret|token|password|private(?:_|-)?key|headers?|env)/i.test(e)}function agentProjectionTerminalReceipt(e){if(!/^(0|[1-9][0-9]*)$/.test(e))throw new Error("invalid agent projection terminal revision");return Object.freeze({schemaVersion:1,state:"blocked",revision:e})}function normalizeAgentProjectionTerminal(e){if("revision,schemaVersion,state"!==Object.keys(e).sort().join(",")||1!==e.schemaVersion||"blocked"!==e.state)throw new Error("invalid agent projection terminal receipt");return agentProjectionTerminalReceipt(e.revision)}function normalizeAgentProjectionIntent(e,t){const n=Object.keys(e).sort(),o=["canonicalHash","coreResultHash","method","operationId","projectionRevision","runtimeAgentUid","runtimeEpoch","runtimeLocalKey","schemaVersion","snapshotRef",...void 0===e.expectedPlatformAgentId?[]:["expectedPlatformAgentId"],...void 0===e.removedBindings?[]:["removedBindings"]].sort();if(n.length!==o.length||n.some((e,t)=>e!==o[t])||1!==e.schemaVersion||!["agent.create","agent.update","agent.delete","agent.applyTemplate"].includes(e.method)||!nonEmptyText(e.operationId)||!nonEmptyText(e.runtimeAgentUid)||!nonEmptyText(e.runtimeLocalKey)||!/^(0|[1-9][0-9]*)$/.test(e.runtimeEpoch)||e.operationId!==t.operationId||e.method!==t.command||e.runtimeEpoch!==t.runtimeEpoch||void 0!==e.expectedPlatformAgentId&&!nonEmptyText(e.expectedPlatformAgentId)||!/^[0-9a-f]{64}$/.test(e.coreResultHash)||!/^(0|[1-9][0-9]*)$/.test(e.projectionRevision)||!/^[0-9a-f]{64}$/.test(e.canonicalHash)||!nonEmptyText(e.snapshotRef)||e.snapshotRef!==projectionSnapshotRef(e.runtimeEpoch,e.projectionRevision,e.canonicalHash)||void 0!==e.removedBindings&&(!Number.isSafeInteger(e.removedBindings)||e.removedBindings<0))throw new Error("invalid agent projection intent");return Object.freeze({...e})}function normalizeAgentProjectionPreparation(e,t){if(isAgentProjectionIntent(e))return normalizeAgentProjectionIntent(e,t);const n=e,o=Object.keys(n).sort(),r=["coreResultHash","errorKind","method","operationId","runtimeAgentUid","runtimeEpoch","runtimeLocalKey","schemaVersion","state",...void 0===n.expectedPlatformAgentId?[]:["expectedPlatformAgentId"],...void 0===n.removedBindings?[]:["removedBindings"]].sort();if(o.length!==r.length||o.some((e,t)=>e!==r[t])||1!==n.schemaVersion||!["agent.create","agent.update","agent.delete","agent.applyTemplate"].includes(n.method)||n.operationId!==t.operationId||n.method!==t.command||n.runtimeEpoch!==t.runtimeEpoch||!nonEmptyText(n.runtimeAgentUid)||!nonEmptyText(n.runtimeLocalKey)||!/^(0|[1-9][0-9]*)$/.test(n.runtimeEpoch)||!/^[0-9a-f]{64}$/.test(n.coreResultHash)||"pending"!==n.state&&"blocked"!==n.state||"snapshot_retryable"!==n.errorKind&&"snapshot_nonretryable"!==n.errorKind||"pending"===n.state!=("snapshot_retryable"===n.errorKind)||void 0!==n.expectedPlatformAgentId&&!nonEmptyText(n.expectedPlatformAgentId)||void 0!==n.removedBindings&&(!Number.isSafeInteger(n.removedBindings)||n.removedBindings<0))throw new Error("invalid agent projection preparation failure");return Object.freeze({...n})}function sameProjectionPreparationBase(e,t){return e.operationId===t.operationId&&e.method===t.method&&e.runtimeEpoch===t.runtimeEpoch&&e.runtimeAgentUid===t.runtimeAgentUid&&e.runtimeLocalKey===t.runtimeLocalKey&&e.coreResultHash===t.coreResultHash&&e.expectedPlatformAgentId===t.expectedPlatformAgentId&&e.removedBindings===t.removedBindings}function isAgentProjectionIntent(e){return"projectionRevision"in e}function projectionSnapshotRef(e,t,n){return`runtime-agent-projection:v1:${e}:${t}:${n}`}function nonEmptyText(e){return"string"==typeof e&&e.length>0}
|
|
1
|
+
import{createHash,randomUUID}from"node:crypto";import{readFile}from"node:fs/promises";import{canonicalizeJcs}from"@beeos-ai/beeos-types/runtime";import{createRuntimeAppendTimingRecorder}from"./runtime-append-timing.js";import{OwnedDirectoryLockContendedError,withOwnedDirectoryLock}from"./owned-directory-lock.js";import{MonotonicJournalSegments}from"./monotonic-journal-segments.js";const HASH_ONLY_RESULT_COMMANDS=new Set(["session.load","session.history","session.list","agent.listProjection","skills.list","models.list","cron.list","cron.status","cron.runs","mcp.list","terminal.ping","terminal.wait"]),SAFE_CANONICAL_RESULT_COMMANDS=new Set(["session.clear","session.setMode","session.setModel","session.cancel","skills.install","skills.uninstall","skills.setEnabled","cron.remove","mcp.prepare","mcp.set","mcp.unset","terminal.input","terminal.resize","terminal.close","terminal.release","terminal.kill","canvas.toggle","canvas.clear","canvas.reference","canvas.dimensions"]);export const runtimeCommandResultPersistencePolicy=e=>SAFE_CANONICAL_RESULT_COMMANDS.has(e)?"canonical_result":"hash_only";export const runtimeCommandIsReplayableQuery=e=>HASH_ONLY_RESULT_COMMANDS.has(e);export const runtimeCommandResultHash=e=>createHash("sha256").update(canonicalizeJcs(e)).digest("hex");const emptyDocument=()=>({version:2,lineage:{journalStoreId:randomUUID(),journalGeneration:"1"},records:[],cancellations:[]}),CHECKPOINT_INTERVAL_MS=6e5,CHECKPOINT_DELTA_COUNT=512,CHECKPOINT_DELTA_BYTES=8388608,CHECKPOINT_FOREGROUND_QUIET_MS=50;export class RuntimeCommandJournalConflictError extends Error{constructor(e){super(e),this.name="RuntimeCommandJournalConflictError"}}export class FileRuntimeCommandJournal{file;retentionMs;now;publication;segments;maintenance;forceCheckpointRequested=!1;maintenanceDue;maintenanceDueAtMs;prunePending=!1;foregroundUpdates=0;foregroundRevision=0;constructor(e,t=6048e5,n=Date.now,o={}){this.file=e,this.retentionMs=t,this.now=n,this.publication=o,this.segments=new MonotonicJournalSegments(e)}async lineage(){return await this.update(e=>({...e.lineage}))}async advanceLineageGeneration(e){return await this.update(t=>{if(t.lineage.journalStoreId!==e.journalStoreId)throw new RuntimeCommandJournalConflictError("journal store changed during incarnation advance");const n=BigInt(t.lineage.journalGeneration),o=BigInt(e.floor),r=(n>o?n:o)+1n;if(r>9223372036854775807n)throw new RuntimeCommandJournalConflictError("journal generation overflow");return t.lineage={journalStoreId:t.lineage.journalStoreId,journalGeneration:String(r)},{...t.lineage}})}async get(e){return(await this.read()).records.find(t=>t.operationId===e)??null}async getCancellation(e){return(await this.read()).cancellations.find(t=>t.operationId===e)??null}async listMcpLiveReleases(){const e=await this.read();return Object.freeze(e.records.flatMap(e=>e.mcpLiveRelease?[e.mcpLiveRelease]:[]))}async listMcpActiveDesiredStates(){const e=await this.read();return Object.freeze(e.records.flatMap(e=>e.mcpActiveDesiredState?[e.mcpActiveDesiredState]:[]))}async recordMcpDesiredStateCommit(e){const t=normalizeMcpDesiredStateCommit(e);return await this.update(e=>{const n=e.records.findIndex(e=>e.operationId===t.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("MCP desired state has no command record");const o=e.records[n];if(assertMcpCommitBindsRecord(t,o),"started"!==o.phase){if(sameMcpDesiredStateCommit(o.mcpDesiredStateCommit,t))return o;throw new RuntimeCommandJournalConflictError("MCP desired state commit crossed its journal boundary")}if(o.mcpDesiredStateCommit){if(sameMcpDesiredStateCommit(o.mcpDesiredStateCommit,t))return o;throw new RuntimeCommandJournalConflictError("MCP desired state commit conflicts with journal")}const r={...o,mcpDesiredStateCommit:t,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString()};return e.records[n]=r,r})}async releaseMcpLiveEffect(e){return await this.update(t=>{const n=t.records.findIndex(t=>t.operationId===e.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("MCP release has no command record");const o=t.records[n];if("effect_committed"!==o.phase&&"projection_committed"!==o.phase)throw new RuntimeCommandJournalConflictError("MCP release requires a committed effect");if(!o.mcpDesiredStateCommit)throw new RuntimeCommandJournalConflictError("MCP release lacks a durable desired-state commit");if("service"===e.source&&!o.messageBinding)throw new RuntimeCommandJournalConflictError("Service MCP release lacks a Message Service request binding");const r=releaseFromCommit(o.mcpDesiredStateCommit,e,new Date(this.now()).toISOString());if(o.mcpLiveRelease){if(sameMcpLiveRelease(o.mcpLiveRelease,r))return o;throw new RuntimeCommandJournalConflictError("MCP release conflicts with journal")}const i={...o,mcpLiveRelease:r,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString()};return t.records[n]=i,i})}async promoteMcpDesiredStateActive(e){return await this.update(t=>{const n=t.records.findIndex(t=>t.operationId===e.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("MCP active promotion has no command record");const o=t.records[n],r=activeFromRelease(o.mcpLiveRelease,e,new Date(this.now()).toISOString());if(o.mcpActiveDesiredState){if(sameMcpActiveDesiredState(o.mcpActiveDesiredState,r))return o;throw new RuntimeCommandJournalConflictError("MCP active desired state conflicts with journal")}const i={...o,mcpActiveDesiredState:r,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString()};return t.records[n]=i,i})}async acceptMessageRequest(e){return await this.update(t=>{let n=t.records.find(t=>t.operationId===e.operationId);if(n||(n={operationId:e.operationId,command:e.command,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,phase:"prepared",revision:1,updatedAt:new Date(this.now()).toISOString()},t.records.push(n)),n.command!==e.command||n.paramsHash!==e.paramsHash||n.runtimeEpoch!==e.runtimeEpoch)throw new RuntimeCommandJournalConflictError("message request conflicts with command journal");const o={requestMessageId:e.requestMessageId,requestHash:e.requestHash,acceptedAt:new Date(this.now()).toISOString()};if(n.messageBinding&&(n.messageBinding.requestMessageId!==o.requestMessageId||n.messageBinding.requestHash!==o.requestHash))throw new RuntimeCommandJournalConflictError("operation reused by a different message request");return n.messageBinding??=o,n})}async observeCancellation(e){return await this.update(t=>{const n=t.cancellations.find(t=>t.eventId===e.eventId);if(n){if(n.operationId!==e.operationId||n.requestMessageId!==e.requestMessageId||n.requestHash!==e.requestHash)throw new RuntimeCommandJournalConflictError("operation cancellation observation conflict");return n}const o=t.cancellations.find(t=>t.operationId===e.operationId);if(o&&(o.requestMessageId!==e.requestMessageId||o.requestHash!==e.requestHash))throw new RuntimeCommandJournalConflictError("operation cancellation request correlation conflict");const r={...e,observedAt:new Date(this.now()).toISOString()};return t.cancellations.push(r),r})}async prepare(e){return await this.update(t=>{const n=t.records.find(t=>t.operationId===e.operationId);if(n){if(n.command!==e.command||n.paramsHash!==e.paramsHash)throw new RuntimeCommandJournalConflictError("operation identity reused with different command or params hash");if(n.runtimeEpoch!==e.runtimeEpoch)throw new RuntimeCommandJournalConflictError("operation belongs to a different runtime epoch");return n}const o={...e,phase:"prepared",revision:1,updatedAt:new Date(this.now()).toISOString()};return t.records.push(o),o})}async transition(e){return await this.update(t=>{const n=t.records.findIndex(t=>t.operationId===e.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("operation was not prepared");const o=t.records[n];if(o.revision!==e.expectedRevision)throw new RuntimeCommandJournalConflictError("journal revision conflict");const r="effect_committed"===o.phase&&"effect_committed"===e.phase&&void 0!==e.agentProjection&&void 0===o.agentProjectionIntent&&"pending"===o.agentProjectionPreparationFailure?.state;if("projection_committed"===o.phase||"failed"===o.phase||"outcome_unknown"===o.phase||"effect_committed"===o.phase&&"projection_committed"!==e.phase&&!r)throw new RuntimeCommandJournalConflictError("terminal journal record is immutable");if(void 0!==e.projectionSnapshot&&"projection_committed"!==e.phase)throw new RuntimeCommandJournalConflictError("projection receipt requires projection_committed phase");if(void 0!==e.agentProjection&&"effect_committed"!==e.phase)throw new RuntimeCommandJournalConflictError("agent projection intent requires effect_committed phase");const i=void 0===e.agentProjection?void 0:normalizeAgentProjectionPreparation(e.agentProjection,o);if(r&&i&&!sameProjectionPreparationBase(o.agentProjectionPreparationFailure,i))throw new RuntimeCommandJournalConflictError("agent projection preparation conflicts with committed operation");const{agentProjectionIntent:a,agentProjectionPreparationFailure:s,...c}=o,d={...void 0===i?o:c,phase:e.phase,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString(),...void 0===e.result?{}:persistedResult(o.command,e.result),...void 0===e.projectionSnapshot?{}:{projectionReceipt:projectionReceipt(e.projectionSnapshot)},...void 0===i?{}:isAgentProjectionIntent(i)?{agentProjectionIntent:i}:{agentProjectionPreparationFailure:i},...void 0===e.errorCode?{}:{errorCode:e.errorCode}};return t.records[n]=d,d})}async recordAgentProjectionIntent(e){return await this.update(t=>{const n=t.records.findIndex(t=>t.operationId===e.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("operation was not prepared");const o=t.records[n];if(o.revision!==e.expectedRevision||"effect_committed"!==o.phase)throw new RuntimeCommandJournalConflictError("projection intent cannot mutate this command journal record");const r=normalizeAgentProjectionIntent(e.intent,o);if(o.agentProjectionIntent){if(canonicalizeJcs(o.agentProjectionIntent)!==canonicalizeJcs(r))throw new RuntimeCommandJournalConflictError("agent projection intent conflicts with committed operation");return o}if("pending"!==o.agentProjectionPreparationFailure?.state||!sameProjectionPreparationBase(o.agentProjectionPreparationFailure,r))throw new RuntimeCommandJournalConflictError("projection intent requires matching retryable preparation failure");const{agentProjectionPreparationFailure:i,...a}=o,s={...a,agentProjectionIntent:r,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString()};return t.records[n]=s,s})}async recordAgentProjectionBlocked(e){return await this.update(t=>{const n=t.records.findIndex(t=>t.operationId===e.operationId);if(n<0)throw new RuntimeCommandJournalConflictError("operation was not prepared");const o=t.records[n];if(o.revision!==e.expectedRevision||"effect_committed"!==o.phase||!o.agentProjectionIntent||o.agentProjectionIntent.projectionRevision!==e.revision)throw new RuntimeCommandJournalConflictError("blocked projection cannot mutate this command journal record");if(o.agentProjectionTerminal){if("blocked"===o.agentProjectionTerminal.state&&o.agentProjectionTerminal.revision===e.revision)return o;throw new RuntimeCommandJournalConflictError("agent projection terminal conflicts with committed operation")}const r=agentProjectionTerminalReceipt(e.revision),i={...o,agentProjectionTerminal:r,revision:o.revision+1,updatedAt:new Date(this.now()).toISOString()};return t.records[n]=i,i})}async compact(){return this.maintenance?await this.maintenance:!1===this.maintenanceDue&&!this.prunePending&&void 0!==this.maintenanceDueAtMs&&Date.now()<this.maintenanceDueAtMs?0:await this.startMaintenance()}async checkpoint(){return this.forceCheckpointRequested=!0,await this.startMaintenance()}async read(){return(await this.readState()).document}async readState(){const e=await this.readLegacy(),t=new Map;if(e){t.set("meta:lineage",{value:e.lineage,logicalRevision:e.lineage.journalGeneration,publisherEpoch:"0"});for(const n of e.records)t.set(`record:${n.operationId}`,{value:n,logicalRevision:String(n.revision),publisherEpoch:"0"});for(const n of e.cancellations)t.set(`cancellation:${n.eventId}`,{value:n,logicalRevision:"1",publisherEpoch:"0"})}const n=await this.segments.readState(t),o=n.values,r=o.get("meta:lineage")?.value;return{document:{version:2,lineage:r??emptyDocument().lineage,records:[...o.entries()].filter(([e])=>e.startsWith("record:")).map(([,e])=>validateRecordReceipts(migrateLegacyCommittedPhase(e.value))),cancellations:[...o.entries()].filter(([e])=>e.startsWith("cancellation:")).map(([,e])=>e.value)},authorityFloor:n.authorityFloor,checkpointAtMs:n.checkpointAtMs,deltaCount:n.deltaCount,deltaBytes:n.deltaBytes,oldestDeltaAtMs:n.oldestDeltaAtMs,hasDurableLineage:o.has("meta:lineage")&&n.hasDurableState}}async readLegacy(){try{const e=JSON.parse(await readFile(this.file,"utf8"));if(!Array.isArray(e.records))throw new Error("unsupported command journal");const t=e.records.map(e=>validateRecordReceipts(migrateLegacyCommittedPhase(e)));if(1===e.version)return{...emptyDocument(),records:t};if(2!==e.version||!e.lineage?.journalStoreId||!/^[1-9][0-9]*$/.test(e.lineage.journalGeneration))throw new Error("unsupported command journal");return{...e,records:t,cancellations:Array.isArray(e.cancellations)?e.cancellations:[]}}catch(e){if("ENOENT"===e.code)return null;throw e}}async update(e){const t=createRuntimeAppendTimingRecorder("journal.update",{file:this.file});let n=!1;this.foregroundUpdates+=1;try{return await withOwnedDirectoryLock(`${this.file}.lock`,async o=>{t.mark("lock");const r=await this.readState();t.mark("read");const i=r.document,a=structuredClone(i),s=e(i),c=[];if(r.hasDurableLineage&&sameValue(a.lineage,i.lineage)||c.push({key:"meta:lineage",logicalRevision:i.lineage.journalGeneration,value:i.lineage}),diffValues(a.records,i.records,e=>e.operationId,e=>String(e.revision),"record:",c),diffValues(a.cancellations,i.cancellations,e=>e.eventId,()=>"1","cancellation:",c),0===c.length)return t.mark("noop"),s;await(this.publication.beforePublish?.(o.epoch)),t.mark("before-publish"),await o.assertOwned(),t.mark("assert-owned");const d=await this.segments.publishDelta(o.epoch,c,r.authorityFloor);t.mark("publish-delta");const m=Date.now();return this.maintenanceDueAtMs=checkpointDueAt(r,1,d,m),n=this.maintenanceDueAtMs<=m,this.maintenanceDue=n,s},{...this.publication.lockOptions,epochFloor:()=>this.segments.authorityFloor()})}finally{this.foregroundUpdates-=1,this.foregroundRevision+=1,t.finish(),n&&this.scheduleMaintenance()}}scheduleMaintenance(){this.startMaintenance().catch(e=>{try{this.publication.onMaintenanceError?this.publication.onMaintenanceError(e):emitMaintenanceWarning(e)}catch(e){emitMaintenanceWarning(e)}})}startMaintenance(){if(this.maintenance)return this.maintenance;const e=(async()=>{let e=0,t=!1;do{let n=this.forceCheckpointRequested;this.forceCheckpointRequested=!1,n||(await this.waitForForegroundQuiet(),n=this.forceCheckpointRequested,this.forceCheckpointRequested=!1);const o=await this.runMaintenance(n);e+=o.removed,t=o.contended}while(this.forceCheckpointRequested||t);return e})().finally(()=>{this.maintenance===e&&(this.maintenance=void 0)});return this.maintenance=e,e}async waitForForegroundQuiet(){for(;;){if(this.forceCheckpointRequested)return;const e=this.foregroundRevision;if(0===this.foregroundUpdates){if(await new Promise(e=>setTimeout(e,50)),this.forceCheckpointRequested||0===this.foregroundUpdates&&this.foregroundRevision===e)return}else await new Promise(e=>setTimeout(e,50))}}async runMaintenance(e){const t=createRuntimeAppendTimingRecorder("journal.checkpoint",{file:this.file});try{if(!e&&this.prunePending)return await this.segments.prune(),this.prunePending=!1,t.mark("prune-pending"),{removed:0,contended:!1};let n=!1;const o=await withOwnedDirectoryLock(`${this.file}.lock`,async o=>{t.mark("lock");const r=await this.readState();if(t.mark("read"),!e&&!checkpointDue(r))return this.maintenanceDue=!1,this.maintenanceDueAtMs=checkpointDueAt(r),t.mark("not-due"),0;const i=r.document,a=this.now()-this.retentionMs,s=i.records.length;i.records=i.records.filter(e=>"prepared"===e.phase||"started"===e.phase||Date.parse(e.updatedAt)>=a);const c=i.cancellations.length;i.cancellations=i.cancellations.filter(e=>Date.parse(e.observedAt)>=a);const d=s-i.records.length+c-i.cancellations.length,m=documentValues(i);return await(this.publication.beforePublish?.(o.epoch)),t.mark("before-publish"),await o.assertOwned(),t.mark("assert-owned"),await this.segments.checkpointSnapshot(o.epoch,m,r.authorityFloor),t.mark("publish-snapshot"),this.maintenanceDue=!1,this.maintenanceDueAtMs=Number.POSITIVE_INFINITY,this.prunePending=!0,n=!0,d},{...this.publication.lockOptions,failIfContended:!e,epochFloor:()=>this.segments.authorityFloor()});return t.mark("lock-released"),n&&(await this.segments.prune(),this.prunePending=!1,t.mark("prune")),{removed:o,contended:!1}}catch(n){if(!e&&n instanceof OwnedDirectoryLockContendedError)return t.mark("deferred-busy"),{removed:0,contended:!0};throw n}finally{t.finish(e?"forced":"scheduled")}}}function checkpointDue(e,t=0,n=0,o=Date.now()){return checkpointDueAt(e,t,n,o)<=o}function checkpointDueAt(e,t=0,n=0,o=Date.now()){const r=e.deltaCount+t,i=e.deltaBytes+n,a=e.oldestDeltaAtMs||(t>0?o:0),s=e.checkpointAtMs||a;return r>=512||i>=8388608?o:r>0&&s>0?s+6e5:Number.POSITIVE_INFINITY}function emitMaintenanceWarning(e){process.emitWarning(e instanceof Error?e.message:String(e),{code:"BEEOS_RUNTIME_JOURNAL_CHECKPOINT_FAILED"})}function diffValues(e,t,n,o,r,i){const a=new Map(e.map(e=>[n(e),e])),s=new Map(t.map(e=>[n(e),e]));for(const[e,t]of s){const n=a.get(e);void 0!==n&&sameValue(n,t)||i.push({key:`${r}${e}`,logicalRevision:o(t),value:t})}for(const[e,t]of a)s.has(e)||i.push({key:`${r}${e}`,logicalRevision:o(t),tombstone:!0})}function documentValues(e){return[{key:"meta:lineage",logicalRevision:e.lineage.journalGeneration,value:e.lineage},...e.records.map(e=>({key:`record:${e.operationId}`,logicalRevision:String(e.revision),value:e})),...e.cancellations.map(e=>({key:`cancellation:${e.eventId}`,logicalRevision:"1",value:e}))]}function sameValue(e,t){return canonicalizeJcs(e)===canonicalizeJcs(t)}function migrateLegacyCommittedPhase(e){return{...e,phase:"committed"===e.phase?"effect_committed":e.phase}}export class InMemoryRuntimeCommandJournal{records=new Map;cancellations=new Map;async get(e){return this.records.get(e)??null}async getCancellation(e){return[...this.cancellations.values()].find(t=>t.operationId===e)??null}async listMcpLiveReleases(){return Object.freeze([...this.records.values()].flatMap(e=>e.mcpLiveRelease?[e.mcpLiveRelease]:[]))}async listMcpActiveDesiredStates(){return Object.freeze([...this.records.values()].flatMap(e=>e.mcpActiveDesiredState?[e.mcpActiveDesiredState]:[]))}async recordMcpDesiredStateCommit(e){const t=normalizeMcpDesiredStateCommit(e),n=this.records.get(t.operationId);if(!n)throw new RuntimeCommandJournalConflictError("MCP desired state has no command record");if(assertMcpCommitBindsRecord(t,n),"started"!==n.phase){if(sameMcpDesiredStateCommit(n.mcpDesiredStateCommit,t))return n;throw new RuntimeCommandJournalConflictError("MCP desired state commit crossed its journal boundary")}if(n.mcpDesiredStateCommit){if(sameMcpDesiredStateCommit(n.mcpDesiredStateCommit,t))return n;throw new RuntimeCommandJournalConflictError("MCP desired state commit conflicts with journal")}const o={...n,mcpDesiredStateCommit:t,revision:n.revision+1,updatedAt:(new Date).toISOString()};return this.records.set(t.operationId,o),o}async releaseMcpLiveEffect(e){const t=this.records.get(e.operationId);if(!t)throw new RuntimeCommandJournalConflictError("MCP release has no command record");if("effect_committed"!==t.phase&&"projection_committed"!==t.phase)throw new RuntimeCommandJournalConflictError("MCP release requires a committed effect");if(!t.mcpDesiredStateCommit)throw new RuntimeCommandJournalConflictError("MCP release lacks a durable desired-state commit");if("service"===e.source&&!t.messageBinding)throw new RuntimeCommandJournalConflictError("Service MCP release lacks a Message Service request binding");const n=releaseFromCommit(t.mcpDesiredStateCommit,e,(new Date).toISOString());if(t.mcpLiveRelease){if(sameMcpLiveRelease(t.mcpLiveRelease,n))return t;throw new RuntimeCommandJournalConflictError("MCP release conflicts with journal")}const o={...t,mcpLiveRelease:n,revision:t.revision+1,updatedAt:(new Date).toISOString()};return this.records.set(e.operationId,o),o}async promoteMcpDesiredStateActive(e){const t=this.records.get(e.operationId);if(!t)throw new RuntimeCommandJournalConflictError("MCP active promotion has no command record");const n=activeFromRelease(t.mcpLiveRelease,e,(new Date).toISOString());if(t.mcpActiveDesiredState){if(sameMcpActiveDesiredState(t.mcpActiveDesiredState,n))return t;throw new RuntimeCommandJournalConflictError("MCP active desired state conflicts with journal")}const o={...t,mcpActiveDesiredState:n,revision:t.revision+1,updatedAt:(new Date).toISOString()};return this.records.set(e.operationId,o),o}async acceptMessageRequest(e){let t=this.records.get(e.operationId);if(t||(t={operationId:e.operationId,command:e.command,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,phase:"prepared",revision:1,updatedAt:(new Date).toISOString()},this.records.set(e.operationId,t)),t.command!==e.command||t.paramsHash!==e.paramsHash||t.runtimeEpoch!==e.runtimeEpoch||t.messageBinding&&(t.messageBinding.requestMessageId!==e.requestMessageId||t.messageBinding.requestHash!==e.requestHash))throw new RuntimeCommandJournalConflictError("message request conflicts with command journal");return t.messageBinding??={requestMessageId:e.requestMessageId,requestHash:e.requestHash,acceptedAt:(new Date).toISOString()},t}async observeCancellation(e){const t=this.cancellations.get(e.eventId);if(t){if(t.operationId!==e.operationId||t.requestMessageId!==e.requestMessageId||t.requestHash!==e.requestHash)throw new RuntimeCommandJournalConflictError("operation cancellation observation conflict");return t}const n=[...this.cancellations.values()].find(t=>t.operationId===e.operationId);if(n&&(n.requestMessageId!==e.requestMessageId||n.requestHash!==e.requestHash))throw new RuntimeCommandJournalConflictError("operation cancellation request correlation conflict");const o={...e,observedAt:(new Date).toISOString()};return this.cancellations.set(e.eventId,o),o}async prepare(e){const t=this.records.get(e.operationId);if(t){if(t.command!==e.command||t.paramsHash!==e.paramsHash||t.runtimeEpoch!==e.runtimeEpoch)throw new RuntimeCommandJournalConflictError("operation identity conflict");return t}const n={...e,phase:"prepared",revision:1,updatedAt:(new Date).toISOString()};return this.records.set(e.operationId,n),n}async transition(e){const t=this.records.get(e.operationId);if(!t||t.revision!==e.expectedRevision)throw new RuntimeCommandJournalConflictError("revision conflict");const n="effect_committed"===t.phase&&"effect_committed"===e.phase&&void 0!==e.agentProjection&&void 0===t.agentProjectionIntent&&"pending"===t.agentProjectionPreparationFailure?.state;if("projection_committed"===t.phase||"failed"===t.phase||"outcome_unknown"===t.phase||"effect_committed"===t.phase&&"projection_committed"!==e.phase&&!n)throw new RuntimeCommandJournalConflictError("terminal journal record is immutable");if(void 0!==e.projectionSnapshot&&"projection_committed"!==e.phase)throw new RuntimeCommandJournalConflictError("projection receipt requires projection_committed phase");if(void 0!==e.agentProjection&&"effect_committed"!==e.phase)throw new RuntimeCommandJournalConflictError("agent projection intent requires effect_committed phase");const o=void 0===e.agentProjection?void 0:normalizeAgentProjectionPreparation(e.agentProjection,t);if(n&&o&&!sameProjectionPreparationBase(t.agentProjectionPreparationFailure,o))throw new RuntimeCommandJournalConflictError("agent projection preparation conflicts with committed operation");const{agentProjectionIntent:r,agentProjectionPreparationFailure:i,...a}=t,s={...void 0===o?t:a,phase:e.phase,revision:t.revision+1,updatedAt:(new Date).toISOString(),...void 0===e.result?{}:persistedResult(t.command,e.result),...void 0===e.projectionSnapshot?{}:{projectionReceipt:projectionReceipt(e.projectionSnapshot)},...void 0===o?{}:isAgentProjectionIntent(o)?{agentProjectionIntent:o}:{agentProjectionPreparationFailure:o},...void 0===e.errorCode?{}:{errorCode:e.errorCode}};return this.records.set(e.operationId,s),s}async recordAgentProjectionIntent(e){const t=this.records.get(e.operationId);if(!t||t.revision!==e.expectedRevision||"effect_committed"!==t.phase)throw new RuntimeCommandJournalConflictError("projection intent cannot mutate this command journal record");const n=normalizeAgentProjectionIntent(e.intent,t);if(t.agentProjectionIntent){if(canonicalizeJcs(t.agentProjectionIntent)!==canonicalizeJcs(n))throw new RuntimeCommandJournalConflictError("agent projection intent conflicts with committed operation");return t}if("pending"!==t.agentProjectionPreparationFailure?.state||!sameProjectionPreparationBase(t.agentProjectionPreparationFailure,n))throw new RuntimeCommandJournalConflictError("projection intent requires matching retryable preparation failure");const{agentProjectionPreparationFailure:o,...r}=t,i={...r,agentProjectionIntent:n,revision:t.revision+1,updatedAt:(new Date).toISOString()};return this.records.set(e.operationId,i),i}async recordAgentProjectionBlocked(e){const t=this.records.get(e.operationId);if(!t||t.revision!==e.expectedRevision||"effect_committed"!==t.phase||!t.agentProjectionIntent||t.agentProjectionIntent.projectionRevision!==e.revision)throw new RuntimeCommandJournalConflictError("blocked projection cannot mutate this command journal record");if(t.agentProjectionTerminal){if("blocked"===t.agentProjectionTerminal.state&&t.agentProjectionTerminal.revision===e.revision)return t;throw new RuntimeCommandJournalConflictError("agent projection terminal conflicts with committed operation")}const n={...t,agentProjectionTerminal:agentProjectionTerminalReceipt(e.revision),revision:t.revision+1,updatedAt:(new Date).toISOString()};return this.records.set(e.operationId,n),n}async compact(){return 0}async checkpoint(){return 0}}function persistedResult(e,t){return"canonical_result"===runtimeCommandResultPersistencePolicy(e)?{result:t}:{resultReceipt:{policy:"hash_only",resultHash:runtimeCommandResultHash(t),redacted:{kind:runtimeCommandIsReplayableQuery(e)?"query_result":"mutation_result",command:e}}}}function projectionReceipt(e){if("synced"!==e.state||!/^(0|[1-9][0-9]*)$/.test(e.revision))throw new Error("invalid projection revision");if(void 0!==e.platformAgentId&&!/^[a-zA-Z0-9._:-]{1,256}$/.test(e.platformAgentId))throw new Error("invalid projection platform agent id");const t=void 0===e.mcpReceipt?void 0:normalizeMcpProjectionReceipt(e.mcpReceipt),n=Object.freeze({revision:e.revision,state:"synced",..."string"==typeof e.platformAgentId&&e.platformAgentId?{platformAgentId:e.platformAgentId}:{},...t?{mcpReceipt:t}:{}});return Object.freeze({schemaVersion:1,revision:n.revision,snapshot:n,snapshotHash:runtimeCommandResultHash(n)})}function validateRecordReceipts(e){if(void 0!==e.agentProjectionIntent&&void 0!==e.agentProjectionPreparationFailure)throw new Error("agent projection journal record is ambiguous");const t=void 0!==e.agentProjectionIntent?{...e,agentProjectionIntent:normalizeAgentProjectionIntent(e.agentProjectionIntent,e)}:void 0!==e.agentProjectionPreparationFailure?{...e,agentProjectionPreparationFailure:normalizeAgentProjectionPreparation(e.agentProjectionPreparationFailure,e)}:e,n=void 0===t.agentProjectionTerminal?t:{...t,agentProjectionTerminal:normalizeAgentProjectionTerminal(t.agentProjectionTerminal)};if(n.agentProjectionTerminal&&(!n.agentProjectionIntent||"effect_committed"!==n.phase||n.agentProjectionIntent.projectionRevision!==n.agentProjectionTerminal.revision))throw new Error("invalid agent projection terminal receipt");const o=void 0===n.mcpDesiredStateCommit?void 0:normalizeMcpDesiredStateCommit(n.mcpDesiredStateCommit);o&&assertMcpCommitBindsRecord(o,n);const r=void 0===n.mcpLiveRelease?void 0:normalizeMcpLiveRelease(n.mcpLiveRelease);if(r&&(!o||!sameMcpDesiredStateCommit(o,r)||"effect_committed"!==n.phase&&"projection_committed"!==n.phase||"service"===r.source&&!n.messageBinding))throw new Error("invalid MCP live release receipt");const i=void 0===n.mcpActiveDesiredState?void 0:normalizeMcpActiveDesiredState(n.mcpActiveDesiredState);if(i&&(!r||!sameMcpDesiredStateCommit(i,r)||i.effectRecordHash!==r.effectRecordHash||i.releasedAt!==r.releasedAt))throw new Error("invalid MCP active desired-state receipt");const a={...n,...o?{mcpDesiredStateCommit:o}:{},...r?{mcpLiveRelease:r}:{},...i?{mcpActiveDesiredState:i}:{}};if(!a.projectionReceipt)return a;const s=a.projectionReceipt,c=["revision","state",...void 0===s.snapshot?.platformAgentId?[]:["platformAgentId"],...void 0===s.snapshot?.mcpReceipt?[]:["mcpReceipt"]].sort().join(",");if("revision,schemaVersion,snapshot,snapshotHash"!==Object.keys(s).sort().join(",")||Object.keys(s.snapshot??{}).sort().join(",")!==c||"projection_committed"!==a.phase||1!==s.schemaVersion||!/^(0|[1-9][0-9]*)$/.test(s.revision)||"synced"!==s.snapshot?.state||s.snapshot.revision!==s.revision)throw new Error("invalid projection receipt");const d=projectionReceipt(s.snapshot),m=d.snapshot.mcpReceipt;if(m&&(m.operationId!==a.operationId||m.method!==a.command||m.runtimeEpoch!==a.runtimeEpoch))throw new Error("MCP projection receipt does not bind journal operation");if(d.snapshotHash!==s.snapshotHash)throw new Error("invalid projection receipt hash");return{...a,projectionReceipt:d}}function normalizeMcpDesiredStateCommit(e){if(!e||"object"!=typeof e||"desiredStateHash,desiredStateRevision,method,operationId,paramsHash,runtimeEpoch,schemaVersion,server,source"!==Object.keys(e).sort().join(",")||1!==e.schemaVersion||"service"!==e.source&&"acp_local"!==e.source||!safeReceiptIdentifier(e.operationId)||"mcp.set"!==e.method&&"mcp.unset"!==e.method||!isSha256(e.paramsHash)||!/^(0|[1-9][0-9]*)$/.test(e.runtimeEpoch)||!/^(0|[1-9][0-9]*)$/.test(e.desiredStateRevision)||!isSha256(e.desiredStateHash))throw new Error("invalid MCP desired-state commit");return Object.freeze({schemaVersion:1,source:e.source,operationId:e.operationId,method:e.method,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,desiredStateRevision:e.desiredStateRevision,desiredStateHash:e.desiredStateHash,server:normalizeMcpReleaseServer(e.server)})}function normalizeMcpLiveRelease(e){if(!e||"object"!=typeof e)throw new Error("invalid MCP live release receipt");const t=["desiredStateHash","desiredStateRevision","method","operationId","paramsHash","releasedAt","runtimeEpoch","schemaVersion","server","source",..."service"===e.source?["effectRecordHash"]:[]].sort().join(",");if(Object.keys(e).sort().join(",")!==t||"service"===e.source&&!isSha256(e.effectRecordHash)||"acp_local"===e.source&&void 0!==e.effectRecordHash||"string"!=typeof e.releasedAt||!Number.isFinite(Date.parse(e.releasedAt)))throw new Error("invalid MCP live release receipt");const n=normalizeMcpDesiredStateCommit({schemaVersion:e.schemaVersion,source:e.source,operationId:e.operationId,method:e.method,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,desiredStateRevision:e.desiredStateRevision,desiredStateHash:e.desiredStateHash,server:e.server});return Object.freeze({...n,...e.effectRecordHash?{effectRecordHash:e.effectRecordHash}:{},releasedAt:e.releasedAt})}function normalizeMcpActiveDesiredState(e){if(!e||"object"!=typeof e)throw new Error("invalid MCP active desired-state receipt");const t=["activatedAt","desiredStateHash","desiredStateRevision","method","operationId","paramsHash","releasedAt","runtimeEpoch","schemaVersion","server","source",..."service"===e.source?["effectRecordHash","terminalMessageId"]:[]].sort().join(",");if(Object.keys(e).sort().join(",")!==t||"string"!=typeof e.activatedAt||!Number.isFinite(Date.parse(e.activatedAt))||"service"===e.source&&!safeReceiptIdentifier(e.terminalMessageId))throw new Error("invalid MCP active desired-state receipt");const n=normalizeMcpLiveRelease({schemaVersion:e.schemaVersion,source:e.source,operationId:e.operationId,method:e.method,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,desiredStateRevision:e.desiredStateRevision,desiredStateHash:e.desiredStateHash,server:e.server,releasedAt:e.releasedAt,...e.effectRecordHash?{effectRecordHash:e.effectRecordHash}:{}});return Object.freeze({...n,...e.terminalMessageId?{terminalMessageId:e.terminalMessageId}:{},activatedAt:e.activatedAt})}function normalizeMcpReleaseServer(e){const t=e&&"object"==typeof e?Object.keys(e).sort().join(","):"",n=!0===e?.removed;if(!(t===(n?"name,removed":void 0===e?.credentialRef?"definitionRef,definitionSha256,name,version":"credentialRef,definitionRef,definitionSha256,name,version")&&safeReceiptIdentifier(e?.name)&&(n||safeMcpReference(e?.definitionRef)&&safeMcpReference(e?.version)&&isSha256(e?.definitionSha256)&&(void 0===e?.credentialRef||safeMcpReference(e.credentialRef)))))throw new Error("invalid MCP desired-state server identity");return Object.freeze(n?{name:e.name,removed:!0}:{name:e.name,definitionRef:e.definitionRef,version:e.version,definitionSha256:e.definitionSha256,...e.credentialRef?{credentialRef:e.credentialRef}:{}})}function assertMcpCommitBindsRecord(e,t){if(e.operationId!==t.operationId||e.method!==t.command||e.paramsHash!==t.paramsHash||e.runtimeEpoch!==t.runtimeEpoch)throw new RuntimeCommandJournalConflictError("MCP desired-state commit does not bind command journal")}function releaseFromCommit(e,t,n){if(t.operationId!==e.operationId||t.source!==e.source||"service"===t.source&&!isSha256(t.effectRecordHash)||"acp_local"===t.source&&void 0!==t.effectRecordHash)throw new RuntimeCommandJournalConflictError("MCP live release proof does not bind desired state");return Object.freeze({...e,...t.effectRecordHash?{effectRecordHash:t.effectRecordHash}:{},releasedAt:n})}function activeFromRelease(e,t,n){if(!(e&&t.operationId===e.operationId&&t.source===e.source&&Number.isFinite(Date.parse(n))&&("service"!==t.source||isSha256(t.effectRecordHash)&&t.effectRecordHash===e.effectRecordHash&&safeReceiptIdentifier(t.terminalMessageId))&&("acp_local"!==t.source||void 0===t.effectRecordHash&&void 0===t.terminalMessageId)))throw new RuntimeCommandJournalConflictError("MCP active promotion does not bind terminal release proof");return Object.freeze({...e,...t.terminalMessageId?{terminalMessageId:t.terminalMessageId}:{},activatedAt:n})}function sameMcpDesiredStateCommit(e,t){if(!e||!t)return!1;const n=e=>({schemaVersion:e.schemaVersion,source:e.source,operationId:e.operationId,method:e.method,paramsHash:e.paramsHash,runtimeEpoch:e.runtimeEpoch,desiredStateRevision:e.desiredStateRevision,desiredStateHash:e.desiredStateHash,server:e.server});return canonicalizeJcs(n(e))===canonicalizeJcs(n(t))}function sameMcpLiveRelease(e,t){const n=e=>({...e,releasedAt:""});return canonicalizeJcs(n(e))===canonicalizeJcs(n(t))}function sameMcpActiveDesiredState(e,t){const n=e=>({...e,releasedAt:"",activatedAt:""});return canonicalizeJcs(n(e))===canonicalizeJcs(n(t))}function normalizeMcpProjectionReceipt(e){if(!e||"object"!=typeof e||"desiredStateHash,desiredStateRevision,method,operationId,runtimeEpoch,schemaVersion,server"!==Object.keys(e).sort().join(",")||1!==e.schemaVersion||!safeReceiptIdentifier(e.operationId)||"mcp.set"!==e.method&&"mcp.unset"!==e.method||!/^(0|[1-9][0-9]*)$/.test(e.runtimeEpoch)||!/^(0|[1-9][0-9]*)$/.test(e.desiredStateRevision)||!isSha256(e.desiredStateHash))throw new Error("invalid MCP projection receipt");const t=e.server;if((t&&"object"==typeof t?Object.keys(t).sort().join(","):"")!==(!0===t?.removed?"name,removed":void 0===t?.definitionRef?"name":"definitionRef,definitionSha256,name")||!safeReceiptIdentifier(t?.name)||void 0!==t?.definitionRef&&(!safeReceiptIdentifier(t.definitionRef)||!isSha256(t.definitionSha256)))throw new Error("invalid MCP projection server receipt");return Object.freeze({schemaVersion:1,operationId:e.operationId,method:e.method,runtimeEpoch:e.runtimeEpoch,desiredStateRevision:e.desiredStateRevision,desiredStateHash:e.desiredStateHash,server:Object.freeze(!0===t.removed?{name:t.name,removed:!0}:void 0===t.definitionRef?{name:t.name}:{name:t.name,definitionRef:t.definitionRef,definitionSha256:t.definitionSha256})})}function isSha256(e){return"string"==typeof e&&/^[a-f0-9]{64}$/.test(e)}function safeReceiptIdentifier(e){return"string"==typeof e&&/^[a-zA-Z0-9._:@/-]{1,512}$/.test(e)&&!/(authorization|bearer|credential|secret|token|password|private(?:_|-)?key|headers?|env)/i.test(e)}function safeMcpReference(e){return"string"==typeof e&&/^[a-zA-Z0-9._:@/-]{1,512}$/.test(e)&&!/(authorization|bearer|secret|token|password|private(?:_|-)?key|headers?|env)/i.test(e)}function agentProjectionTerminalReceipt(e){if(!/^(0|[1-9][0-9]*)$/.test(e))throw new Error("invalid agent projection terminal revision");return Object.freeze({schemaVersion:1,state:"blocked",revision:e})}function normalizeAgentProjectionTerminal(e){if("revision,schemaVersion,state"!==Object.keys(e).sort().join(",")||1!==e.schemaVersion||"blocked"!==e.state)throw new Error("invalid agent projection terminal receipt");return agentProjectionTerminalReceipt(e.revision)}function normalizeAgentProjectionIntent(e,t){const n=Object.keys(e).sort(),o=["canonicalHash","coreResultHash","method","operationId","projectionRevision","runtimeAgentUid","runtimeEpoch","runtimeLocalKey","schemaVersion","snapshotRef",...void 0===e.expectedPlatformAgentId?[]:["expectedPlatformAgentId"],...void 0===e.removedBindings?[]:["removedBindings"]].sort();if(n.length!==o.length||n.some((e,t)=>e!==o[t])||1!==e.schemaVersion||!["agent.create","agent.update","agent.delete","agent.applyTemplate"].includes(e.method)||!nonEmptyText(e.operationId)||!nonEmptyText(e.runtimeAgentUid)||!nonEmptyText(e.runtimeLocalKey)||!/^(0|[1-9][0-9]*)$/.test(e.runtimeEpoch)||e.operationId!==t.operationId||e.method!==t.command||e.runtimeEpoch!==t.runtimeEpoch||void 0!==e.expectedPlatformAgentId&&!nonEmptyText(e.expectedPlatformAgentId)||!/^[0-9a-f]{64}$/.test(e.coreResultHash)||!/^(0|[1-9][0-9]*)$/.test(e.projectionRevision)||!/^[0-9a-f]{64}$/.test(e.canonicalHash)||!nonEmptyText(e.snapshotRef)||e.snapshotRef!==projectionSnapshotRef(e.runtimeEpoch,e.projectionRevision,e.canonicalHash)||void 0!==e.removedBindings&&(!Number.isSafeInteger(e.removedBindings)||e.removedBindings<0))throw new Error("invalid agent projection intent");return Object.freeze({...e})}function normalizeAgentProjectionPreparation(e,t){if(isAgentProjectionIntent(e))return normalizeAgentProjectionIntent(e,t);const n=e,o=Object.keys(n).sort(),r=["coreResultHash","errorKind","method","operationId","runtimeAgentUid","runtimeEpoch","runtimeLocalKey","schemaVersion","state",...void 0===n.expectedPlatformAgentId?[]:["expectedPlatformAgentId"],...void 0===n.removedBindings?[]:["removedBindings"]].sort();if(o.length!==r.length||o.some((e,t)=>e!==r[t])||1!==n.schemaVersion||!["agent.create","agent.update","agent.delete","agent.applyTemplate"].includes(n.method)||n.operationId!==t.operationId||n.method!==t.command||n.runtimeEpoch!==t.runtimeEpoch||!nonEmptyText(n.runtimeAgentUid)||!nonEmptyText(n.runtimeLocalKey)||!/^(0|[1-9][0-9]*)$/.test(n.runtimeEpoch)||!/^[0-9a-f]{64}$/.test(n.coreResultHash)||"pending"!==n.state&&"blocked"!==n.state||"snapshot_retryable"!==n.errorKind&&"snapshot_nonretryable"!==n.errorKind||"pending"===n.state!=("snapshot_retryable"===n.errorKind)||void 0!==n.expectedPlatformAgentId&&!nonEmptyText(n.expectedPlatformAgentId)||void 0!==n.removedBindings&&(!Number.isSafeInteger(n.removedBindings)||n.removedBindings<0))throw new Error("invalid agent projection preparation failure");return Object.freeze({...n})}function sameProjectionPreparationBase(e,t){return e.operationId===t.operationId&&e.method===t.method&&e.runtimeEpoch===t.runtimeEpoch&&e.runtimeAgentUid===t.runtimeAgentUid&&e.runtimeLocalKey===t.runtimeLocalKey&&e.coreResultHash===t.coreResultHash&&e.expectedPlatformAgentId===t.expectedPlatformAgentId&&e.removedBindings===t.removedBindings}function isAgentProjectionIntent(e){return"projectionRevision"in e}function projectionSnapshotRef(e,t,n){return`runtime-agent-projection:v1:${e}:${t}:${n}`}function nonEmptyText(e){return"string"==typeof e&&e.length>0}
|
|
@@ -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";import{parseRfc3339Instant}from"../acp-gateway/mcp-desired-state-store.js";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 n;try{n=await s.json()}catch{throw integrity("MCP authority response is invalid","response_not_json")}const o=validateRuntimeMcpResourceRedemptionCompletion({request:i,binding:t,reservation:r,expectedDisposition:n.disposition,result:n,sha256Utf8:sha256Utf8});if(!o.valid)throw integrity("MCP resource integrity failed",`violations=${o.violations.join(",")}`);if(!isPlainObject(n.resource.config))throw integrity("MCP authority payload must contain public object config","config_not_object");const a=void 0===n.resource.credential?void 0:credentialMaterial(n.resource.credential);if(a&&!a.expiresAt&&this.options.requireCredentialExpiry)throw integrity("MCP credential has no expiry","credential_expiry_missing");return{descriptor:e,config:Object.freeze({...n.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),n=new Uint8Array(await s.arrayBuffer()),o=skillHeaders(s),a=validateRuntimeSkillResourceRedemptionCompletion({request:i,binding:t,reservation:r,expectedDisposition:o["X-BeeOS-Redemption-Disposition"],headers:o,chunks:[n],sha256Utf8:sha256Utf8,sha256Bytes:sha256Bytes});if(!a.valid)throw integrity("skill resource integrity failed",`violations=${a.violations.join(",")} bytes=${n.byteLength}`);return{descriptor:e,parsed:await this.options.parseSkillArtifact(n)}}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},n=normalizeRuntimeResourceRedemptionHashPayload(s,e);if(!n)throw resolution("resource redemption request does not match immutable binding","request_binding_mismatch");const o=hashRuntimeResourceRedemptionPayload(n,sha256Utf8);if(i&&i.requestHash!==o)throw resolution("resource redemption intent changed","redemption_intent_changed");return this.attempts.set(e.resourceRef,{redemptionId:r,requestHash:o}),{request:s,reservation:{state:"reserved",redemptionId:r,redemptionRequestHash:o}}}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&&"expiresAt"!==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");const r=credentialExpiry(e.expiresAt);return Object.freeze({...t?{headers:Object.freeze(t)}:{},...i?{env:Object.freeze(i)}:{},...r?{expiresAt:r}:{}})}function credentialExpiry(e){if(void 0===e)return;const t=parseRfc3339Instant(e);if(!t)throw integrity("MCP credential expiry is invalid","credential_expiry_invalid");return t}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.
|
|
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 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){this.options=t,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 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"),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}`),"fenced"===t&&this.publish(null,"fenced");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,e){for(const i of this.listeners)try{i(t,e)}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 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
|
+
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}`),"fenced"===t&&this.publish(null,"fenced");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,e){for(const i of this.listeners)try{i(t,e)}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{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{RuntimeJwksVerifier}from"./runtime-jwks-verifier.js";import{GatewayGrantJwksVerifier}from"./split-runtime-authorization-verifier.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,{agentGatewayUrl:new URL(e.agentGatewayUrl).toString()})}}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,agentGatewayUrl:new URL(e.agentGatewayUrl).toString(),boundAgentFetch:e.boundAgentFetch})}}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])};let t;if(e.authorizationAdapter)try{t=await probeGatewayGrantJwks(e.authorizationAdapter)}catch{}const r=e.transportAdapter?transportOptions.get(e.transportAdapter):void 0;if(!r?.messageClient||!r.configuredServiceUrl)return{status:"unavailable",blockers:Object.freeze([TRANSPORT_BLOCKER,...t?[]:[JWKS_BLOCKER]])};if(!t)return{status:"unavailable",blockers:Object.freeze([JWKS_BLOCKER])};const n=runtimeMethods(),a=e.attemptPorts??runtimeMessageAttemptPorts(r,r.configuredServiceUrl);return{status:"ready",blockers:[],capabilityBlockers:CAPABILITY_BLOCKERS,serviceMethods:n,factory:new MsRuntimeMessageChannelConsumerFactory({client:r.messageClient,verifier:t,ports:a,journal:e.commandJournal,allowedMethods:new Set(n),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}:{}}}async function probeGatewayGrantJwks(e){const t=grantAdapterOptions.get(e);if(!t)throw new Error("untrusted Gateway grant readiness adapter");const r=t.agentGatewayUrl.replace(/\/+$/,""),n=new GatewayGrantJwksVerifier(new RuntimeJwksVerifier(`${r}/.well-known/runtime-execution-grant-jwks.json`));return await n.refresh(!0),n}export function runtimeMessageAttemptPorts(e,t){return{async resolve({request:r,command:n,executionGrant:a,getLease:s,journalStoreId:i,journalGeneration:o,journalRecord:c,abortSignal:u}){const d="skills.install"===n.name||"agent.applyTemplate"===n.name?n.params.artifact:void 0,m="mcp.prepare"===n.name||"mcp.set"===n.name?n.params.definition:void 0;if((d||m)&&(r.resourceBindingContractRevision!==RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION||!r.resourceBindings))throw new RuntimeResourceResolutionError("resolution_rejected","resource-bound Service delivery requires the Types 4.1 binding carrier");const l=new HttpRuntimeOperationResourceResolver({gatewayUrl:e.agentGatewayUrl,operationId:r.operationId,requestMessageId:r.requestMessageId,instanceId:r.instanceId,paramsHash:r.paramsHash,bindings:r.resourceBindings??[],getAuthorization:()=>{const e=s();return{executionGrant:a,runtimeLeaseCredential:e.runtimeLeaseCredential,fence:deliveryFence(r,e,i,o)}},fetchAuthorized:async(t,r)=>await e.boundAgentFetch(t,r??{}),parseSkillArtifact:e=>parseAndValidateTemplatePackage(Buffer.from(e)),signal:u});if("prepared"!==c.phase&&"started"!==c.phase||(d&&await l.readVerifiedArtifact(d),m&&await l.resolveMcpDefinition(m)),"session.setReasoning"===n.name)return{resources:l,sessionReasoningProjection:{project:async({conversationId:n,reasoning:a})=>{const i=s();await projectSessionReasoning({messageServiceUrl:t,conversationId:n,reasoning:a,operationId:r.operationId,requestMessageId:r.requestMessageId,requestHash:r.requestHash,runtimeLeaseCredential:i.runtimeLeaseCredential,fetchAuthorized:(t,r)=>e.messageService.fetchRuntimeChannel(t,{runtimeLeaseCredential:i.runtimeLeaseCredential},r)})}}};if("session.setModel"===n.name)return{resources:l,sessionModelProjection:{project:async({conversationId:n,modelOverrideId:a})=>{const i=s(),o=new MessageServiceSessionModelHttpAuthority({messageServiceUrl:t,fetchAuthorized:async(t,r)=>await e.messageService.fetchRuntimeChannel(t,{runtimeLeaseCredential:i.runtimeLeaseCredential},r)});return await o.project({conversationId:n,operationId:r.operationId,requestMessageId:r.requestMessageId,requestHash:r.requestHash,modelOverrideId:a,runtimeLeaseCredential:i.runtimeLeaseCredential})}}};if("session.clear"!==n.name)return{resources:l};n.context.conversation;const p=s(),R=new MessageServiceConversationClearHttpAuthority({messageServiceUrl:t,runtimeLeaseCredential:p.runtimeLeaseCredential,fetchAuthorized:async(t,r)=>await e.messageService.fetchRuntimeChannel(t,{runtimeLeaseCredential:p.runtimeLeaseCredential},r)});return{resources:l,historyBoundary:new MessageServiceConversationHistoryBoundary({operationId:r.operationId,requestMessageId:r.requestMessageId,requestHash:r.requestHash,fence:deliveryFence(r,p,i,o),authority:R})}}}}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 deliveryFence(e,t,r,n){if(t.handlerIdentity!==e.runtimeHandlerIdentity||t.runtimeEpoch!==e.dispatchEpoch)throw new Error("runtime delivery fence does not match the retained request");return{claimId:e.requestMessageId,handlerIdentity:t.handlerIdentity,runtimeEpoch:t.runtimeEpoch,fencingToken:t.runtimeEpoch,journalStoreId:r,journalGeneration:n}}import{projectSessionReasoning}from"./message-service-session-reasoning-http-authority.js";
|
|
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","mcp/list","mcp/set","mcp/unset"]);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,{requireCredentialExpiry:!0}),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,t={}){return{async resolve({request:n,command:a,executionGrant:o,getLease:s,journalStoreId:i,journalGeneration:c,journalRecord:u,abortSignal:d}){const l="resourceBindings"in n?n.resourceBindings:void 0,m="resourceBindingContractRevision"in n?n.resourceBindingContractRevision:void 0,p="skills.install"===a.name||"agent.applyTemplate"===a.name?a.params.artifact:void 0,R="mcp.prepare"===a.name||"mcp.set"===a.name?a.params.definition:void 0;if((p||R)&&(m!==RUNTIME_RESOURCE_BINDING_CONTRACT_REVISION||!l))throw new RuntimeResourceResolutionError("resolution_rejected","resource-bound Service delivery requires the Types 4.1 binding carrier",void 0,`binding_contract_revision=${m??"absent"} bindings=${l?"present":"absent"}`);const C=new HttpRuntimeOperationResourceResolver({gateway:e.gateway,operationId:n.operationId,requestMessageId:n.requestMessageId,instanceId:n.instanceId,paramsHash:n.paramsHash,bindings:l??[],getAuthorization:()=>{const e=s();return{executionGrant:o,runtimeLeaseCredential:e.runtimeLeaseCredential,fence:deliveryFence(n,e,i,c)}},parseSkillArtifact:e=>parseSkillPackage(e),signal:d,...t.requireCredentialExpiry?{requireCredentialExpiry:!0}:{}});if("prepared"!==u.phase&&"started"!==u.phase||(p&&await C.readVerifiedArtifact(p),R&&await C.resolveMcpDefinition(R)),"session.setModel"===a.name){if(!e.messageService)throw new Error("Cloud runtime cannot project a personal session model");const t=e.scopedDeliveryKey;if(!t)throw new Error("session model requires X-Runtime-Delivery-Key");return{resources:C,sessionModelProjection:{project:async({conversationId:e,modelOverrideId:a})=>{const o=s(),i=new MessageServiceSessionModelHttpAuthority({messageServiceUrl:r,scopedDeliveryKey:t,fetchAuthorized:(e,r)=>fetchRuntimeLeaseAttempt(e,r??{})});return await i.project({conversationId:e,operationId:n.operationId,requestMessageId:n.requestMessageId,requestHash:n.requestHash,modelOverrideId:a,runtimeLeaseCredential:o.runtimeLeaseCredential})}}}}if("session.clear"!==a.name)return{resources:C};if(!e.messageService)throw new Error("Cloud runtime cannot access personal conversation history");a.context.conversation;const v=s(),y=new MessageServiceConversationClearHttpAuthority({messageServiceUrl:r,runtimeLeaseCredential:v.runtimeLeaseCredential,fetchAuthorized:(e,r)=>fetchRuntimeLeaseAttempt(e,r??{})});return{resources:C,historyBoundary:new MessageServiceConversationHistoryBoundary({operationId:n.operationId,requestMessageId:n.requestMessageId,requestHash:n.requestHash,fence:deliveryFence(n,v,i,c),authority:y})}}}}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}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID}from"node:crypto";import{performance}from"node:perf_hooks";import{RuntimeCommandError}from"./runtime-command-dispatcher.js";import{ClearConversationUseCase}from"./conversation-clear-use-case.js";import{AROUTER_PROVIDER_ID}from"../media/arouter-config.js";import{getOpenClawNativeSessions}from"./openclaw-native-sessions.js";import{openClawSessionKeysFromList}from"./openclaw-session-key-resolution.js";async function modelSwitchTimingSpan(e,t,i){const s=performance.now();let n="succeeded";try{return await i()}catch(e){throw n="failed",e}finally{e&&process.stderr.write(`[MODEL_SWITCH_TIMING] component=runtime operationId=${e} stage=${t} outcome=${n} durationMs=${(performance.now()-s).toFixed(1)}\n`)}}export class RuntimeSessionControlService{clearRuntime;fallback;activeRuns;constructor(e,t,i){this.clearRuntime=e,this.fallback=t,this.activeRuns=i}async execute(e,t,i){const s=e;if("session.clear"===s.name){if(!i.historyBoundary)throw new RuntimeCommandError("INVALID_PARAMS",`${i.origin} clear attempt lacks its history boundary`);const e=s.context.conversation;return await new ClearConversationUseCase(i.historyBoundary,this.clearRuntime).execute({operationId:s.context.operationId,conversationId:e.runtimeConversationUid,runtimeSessionKey:e.runtimeSessionKey,runtimeEpoch:s.context.dispatchEpoch})}if("session.cancel"===s.name){if(!this.activeRuns)throw new RuntimeCommandError("INVALID_PARAMS","session.cancel active-run authority is not configured");const e=s;return await this.activeRuns.cancelExact({runtimeConversationUid:e.context.conversation.runtimeConversationUid,runtimeSessionKey:e.context.conversation.runtimeSessionKey,historyGeneration:e.context.historyGeneration,targetMessageId:e.params.targetMessageId}),{}}if(!this.fallback)throw new Error(`session command delegate is not configured: ${s.name}`);return await this.fallback.execute(s,t,i)}async projectCommitted(e,t,i){return await(this.fallback?.projectCommitted?.(e,t,i))}}export class OpenClawSessionMetadataService{metadata;constructor(e,t){this.metadata="function"==typeof e?new OpenClawGatewaySessionMetadataPort(e,void 0,void 0,t):e}async execute(e,t,i){const s=e,n=s.context.conversation.runtimeSessionKey,o={lease:t,attempt:i};switch(s.name){case"session.load":return await this.metadata.load(n,o);case"session.rename":{const e=s.params.title.slice(0,64);return await this.metadata.rename(n,e,o)}case"session.delete":return await this.metadata.delete(n,o);case"session.setMode":{const e=s.params.mode;return await this.metadata.setMode(n,e,o)}case"session.setReasoning":{if(!this.metadata.setReasoning)throw new RuntimeCommandError("INVALID_PARAMS","reasoning is not supported");const e=s.params;return await this.metadata.setReasoning(n,e.modelId,e.reasoningOverrideId,o)}case"session.setModel":{const e=s.params.modelOverrideId;if(null!==e&&("string"!=typeof e||!e.trim()))throw new RuntimeCommandError("INVALID_PARAMS","modelOverrideId must be a non-empty string or null");const t=null===e?await modelSwitchTimingSpan(i.operationId,"resolve_agent_default_model",async()=>await this.metadata.resolveAgentDefaultModel(n,o)):void 0;if(null===e&&!t)throw new RuntimeCommandError("AGENT_DEFAULT_MODEL_NOT_CONFIGURED","agent default model is not configured");return await modelSwitchTimingSpan(i.operationId,"metadata_set_model",async()=>await this.metadata.setModel(n,e,t??void 0,o))}}throw new RuntimeCommandError("INVALID_PARAMS","unsupported session metadata command")}async projectCommitted(e,t,i){if("session.setReasoning"===e.name){if("service"===i?.origin){if(!i.sessionReasoningProjection)throw new Error("Message Service reasoning projection unavailable");return Object.freeze({state:"pending",revision:"0"})}return}if("session.setModel"!==e.name)return;const s=e,n=t;if(this.metadata.projectCommittedSetModel&&await this.metadata.projectCommittedSetModel(s.context.conversation.runtimeSessionKey,n),"service"===i?.origin){if(!i.sessionModelProjection)throw new Error("Message Service session model projection is unavailable");return Object.freeze({state:"pending",revision:"0"})}if(!this.metadata.projectCommittedSetModel)throw new Error("session metadata projection is unavailable")}}export class OpenClawGatewaySessionMetadataPort{getGateway;projectModel;liveSessionKeys;declareModel;constructor(e,t,i,s){this.getGateway=e,this.projectModel=t,this.liveSessionKeys=i,this.declareModel=s}async load(e,t){const i=await this.requireExistingOpenClawKey(e,t);return await this.gateway().request("sessions.resolve",{key:i}),{loaded:!0}}async rename(e,t,i){const s=await this.requireExistingOpenClawStoreKey(e,i);return await this.gateway().request("sessions.patch",{key:s,label:t,...await this.requireSessionIdentity(s)}),{title:t}}async delete(e,t){const i=await this.requireExistingOpenClawStoreKey(e,t);return await this.gateway().request("sessions.delete",{key:i}),{deleted:!0}}async setMode(e,t,i){const s="verbose"===t||"detailed"===t?{verboseLevel:"full"}:"reasoning"===t||"thinking"===t?{reasoningLevel:"stream"}:"concise"===t||"default"===t?{verboseLevel:"default"}:null;if(!s)throw new RuntimeCommandError("INVALID_PARAMS",`unsupported session mode: ${t}`);const n=await this.requireExistingOpenClawStoreKey(e,i);if(!isAuthoritativeSetModeAck(await this.gateway().request("sessions.patch",{key:n,...s,...await this.requireSessionIdentity(n)}),n,s))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact target and effective mode");return{mode:t}}async setReasoning(e,t,i,s){let n=this.liveSessionKeys?await this.resolveSetModelKey(e,s):{key:await this.requireExistingOpenClawStoreKey(e,s),materialized:!1};openClawSessionKeysFromList(await this.gateway().request("sessions.list",{includeDerivedTitles:!0})).has(n.key)||(n=await this.materializeSetModelKey(e,n.key,s));const o=n.key,r=await this.requireSessionIdentity(o),a=await this.gateway().request("sessions.list",{includeDerivedTitles:!0}),l=a.sessions?.find(e=>(e.key??e.sessionKey)===o);if((l?.model?toPlatformModelId(l.model.includes("/")?l.model:`${l.modelProvider}/${l.model}`):null)!==t)throw new RuntimeCommandError("INVALID_PARAMS","model changed; refresh reasoning options");const d=await this.gateway().request("models.list",{agentId:runtimeAgentId(o)}),c=d.models?.find(e=>"string"==typeof e.id&&toPlatformModelId(e.id.includes("/")?e.id:`${e.provider}/${e.id}`)===t),m=c?runtimeReasoningOptions(c):void 0;if(!m||null!==i&&!m.levels.some(e=>e.id===i))throw new RuntimeCommandError("INVALID_PARAMS","unsupported reasoning level");const u=await this.gateway().request("sessions.patch",{key:o,thinkingLevel:i,...r}),y=u?.resolved?.model?toPlatformModelId(u.resolved.model.includes("/")?u.resolved.model:`${u.resolved.modelProvider}/${u.resolved.model}`):null;if(!u||!0!==u.ok||u.key!==o||y!==t||!u.entry||(null===i?null!=u.entry.thinkingLevel:u.entry.thinkingLevel!==i))throw new RuntimeCommandError("OUTCOME_UNKNOWN","thinking configuration was not acknowledged");return n.materialized&&this.liveSessionKeys?.registerMaterializedModelKey?.(o),{modelId:t,reasoningOverrideId:i,effectiveReasoningId:i??m.defaultLevel,defaultReasoningId:m.defaultLevel}}async resolveAgentDefaultModel(e,t){const i=runtimeAgentId(this.liveSessionKeys?(await this.resolveSetModelKey(e,t)).key:await this.requireExistingOpenClawKey(e,t)),s=await this.gateway().request("agents.list",{}),n=s?.agents?.find(e=>e.id===i),o=n?.defaultModel??n?.model;if("string"!=typeof o||!o.trim()||o.trim()!==o)return null;const r=toPlatformModelId(o),a=r.indexOf("/");return{modelId:r,...a>0?{modelProvider:r.slice(0,a)}:{}}}async setModel(e,t,i,s){if(null!==t&&!this.declareModel)throw new Error("OpenClaw model configuration runtime is unavailable");const n=null===t?null:await this.declareModel(t),o=s?.attempt.operationId;let r=await modelSwitchTimingSpan(o,"resolve_set_model_key",async()=>await this.resolveSetModelKey(e,s));const a=await this.readSessionIdentity(r.key);a||r.materialized||(r=await this.materializeSetModelKey(e,r.key,s));const l=await modelSwitchTimingSpan(o,"openclaw_sessions_patch",async()=>await this.gateway().request("sessions.patch",{key:r.key,model:n,thinkingLevel:null,...a?{expectedSessionId:a.sessionId,...a.lifecycleRevision?{expectedLifecycleRevision:a.lifecycleRevision}:{}}:{}})),{key:d,materialized:c}=r;if(!isAuthoritativeSetModelAck(l,d,n,t))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact existing session and effective model");const m=l.resolved.model,u=`${l.resolved.modelProvider}/${m}`;if(null!==t&&u!==n)throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the requested override");const y=null===t?toPlatformModelId(u):t;if(null===t&&(!i||y!==i.modelId))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the prevalidated agent default");if(c){const e=await modelSwitchTimingSpan(o,"openclaw_sessions_list_post_materialize",async()=>await this.gateway().request("sessions.list",{includeDerivedTitles:!0}));if(!openClawSessionKeysFromList(e).has(d))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch acknowledged a model-intent session that is absent from the authoritative store");if(!this.liveSessionKeys?.registerMaterializedModelKey)throw new RuntimeCommandError("OUTCOME_UNKNOWN","model-intent session registration authority is unavailable");this.liveSessionKeys.registerMaterializedModelKey(d)}return{...null===t?{}:{modelOverrideId:t},effectiveModelId:y,...l.resolved?.modelProvider?{modelProvider:l.resolved.modelProvider}:{}}}async projectCommittedSetModel(e,t){if(!this.projectModel)throw new Error("session metadata projection is unavailable");const i=await this.requireExistingOpenClawKey(e);await this.projectModel(i,t)}async readSessionIdentity(e){const t=getOpenClawNativeSessions();if(t)return t.getEntry(runtimeAgentId(e),e);const i=await this.gateway().request("sessions.list",{includeDerivedTitles:!0}),s=i?.sessions?.filter(t=>(t.key??t.sessionKey)===e)??[];if(0===s.length)return;const n=s[0];if(1!==s.length||"string"!=typeof n.sessionId||!n.sessionId.trim())throw new RuntimeCommandError("INVALID_PARAMS","OpenClaw session identity is missing or ambiguous");return{sessionId:n.sessionId,..."string"==typeof n.lifecycleRevision&&n.lifecycleRevision?{lifecycleRevision:n.lifecycleRevision}:{}}}async requireSessionIdentity(e){const t=await this.readSessionIdentity(e);if(!t)throw new RuntimeCommandError("INVALID_PARAMS",`OpenClaw session key does not exist (refusing sessions.patch upsert): ${e}`);return{expectedSessionId:t.sessionId,...t.lifecycleRevision?{expectedLifecycleRevision:t.lifecycleRevision}:{}}}async requireExistingOpenClawKey(e,t){if(await(this.liveSessionKeys?.waitForHydration?.()),!this.liveSessionKeys)return e;try{return this.liveSessionKeys.resolveLiveKey(e)}catch(i){if(!t||!isMissingLiveSession(i)||!this.liveSessionKeys.reconcileMissingLiveKey)throw i;return await this.liveSessionKeys.reconcileMissingLiveKey(e,t),this.liveSessionKeys.resolveLiveKey(e)}}async requireExistingOpenClawStoreKey(e,t){const i=await this.requireExistingOpenClawKey(e,t),s=await this.gateway().request("sessions.list",{includeDerivedTitles:!0});if(!openClawSessionKeysFromList(s).has(i))throw new RuntimeCommandError("INVALID_PARAMS",`OpenClaw session key does not exist (refusing sessions.patch upsert): ${i}`);return i}async resolveSetModelKey(e,t){let i;const s="service"===t?.attempt.origin&&void 0!==t.attempt.verifiedMessageGrant;try{i=await this.requireExistingOpenClawKey(e,t)}catch(e){if(!(s&&t&&isMissingLiveSession(e)&&this.liveSessionKeys?.materializeMissingModelKey&&this.liveSessionKeys.registerMaterializedModelKey))throw e}return i?{key:i,materialized:!1}:await this.materializeSetModelKey(e,void 0,t)}async materializeSetModelKey(e,t,i){if(!("service"===i?.attempt.origin&&void 0!==i.attempt.verifiedMessageGrant&&i&&this.liveSessionKeys?.materializeMissingModelKey&&this.liveSessionKeys.registerMaterializedModelKey)){throw new RuntimeCommandError("INVALID_PARAMS",`OpenClaw session key does not exist (refusing sessions.patch upsert): ${t??e}`)}const s=await this.liveSessionKeys.materializeMissingModelKey(e,i);if(t&&s!==t)throw new RuntimeCommandError("INVALID_PARAMS","verified model-intent key conflicts with the live local session");return{key:s,materialized:!0}}gateway(){const e=this.getGateway();if(!e?.isConnected)throw new RuntimeCommandError("GATEWAY_NOT_CONNECTED","Gateway not connected");return e}}function isMissingLiveSession(e){return e instanceof RuntimeCommandError&&"INVALID_PARAMS"===e.code&&e.message.startsWith("no live local session")}function runtimeAgentId(e){const t=e.split(":");return"agent"===t[0]&&t[1]?.trim()?t[1]:"main"}function toPlatformModelId(e){const t=`${AROUTER_PROVIDER_ID}/`;return e.startsWith(t)?e.slice(t.length):e}function isAuthoritativeSetModeAck(e,t,i){if(!e||"object"!=typeof e||Array.isArray(e))return!1;const s=e;if(!0!==s.ok||s.key!==t||!s.entry||"object"!=typeof s.entry||Array.isArray(s.entry))return!1;const n=s.entry;return"verboseLevel"in i?n.verboseLevel===i.verboseLevel:n.reasoningLevel===i.reasoningLevel}function isAuthoritativeSetModelAck(e,t,i,s){if(!e||"object"!=typeof e||Array.isArray(e))return!1;const n=e;if("ok"in n&&!0!==n.ok)return!1;if("key"in n&&n.key!==t)return!1;const o=n.resolved;if(!o||"object"!=typeof o||Array.isArray(o))return!1;const r=o.model,a=o.modelProvider;return!("string"!=typeof r||!r.trim()||"string"!=typeof a||!a.trim())&&(null!==s||null===i)}export class LocalConversationHistoryBoundary{onCommit;kind="local";intents=new Map;convergence=new Map;generations=new Map;constructor(e){this.onCommit=e}currentGeneration(e){return String(this.generations.get(e)??0n)}async prepare(e){const t=this.intents.get(e.operationId);if(t)return t;const i=(new Date).toISOString(),s=this.generations.get(e.conversationId)??0n,n={intentId:randomUUID(),operationId:e.operationId,conversationId:e.conversationId,state:"prepared",runtimeEpoch:e.runtimeEpoch,fromGeneration:String(s),toGeneration:String(s+1n),boundaryOffset:"0",version:"1",createdAt:i,updatedAt:i};return this.intents.set(e.operationId,n),n}async markResetting(e,t){return this.assertState(e,"prepared"),this.convergence.set(e.operationId,t),this.transition(e,"resetting")}async loadRunConvergence(e){const t=this.convergence.get(e.operationId);if(!t)throw new Error("local clear convergence receipt missing");return t}async markResetDone(e){return this.assertState(e,"resetting"),this.transition(e,"reset_done")}async commit(e){return this.assertState(e,"reset_done"),await(this.onCommit?.(e.conversationId)),this.generations.set(e.conversationId,BigInt(e.toGeneration)),this.transition(e,"committed")}async abortPrepared(e){this.assertState(e,"prepared"),this.transition(e,"aborted")}transition(e,t){const i={...e,state:t,version:String(BigInt(e.version)+1n),updatedAt:(new Date).toISOString()};return this.intents.set(e.operationId,i),i}assertState(e,t){const i=this.intents.get(e.operationId);if(!i||i.version!==e.version||i.state!==t)throw new Error(`local clear transition fenced: expected ${t}`)}}import{runtimeReasoningOptions}from"./runtime-reasoning.js";
|
|
1
|
+
import{randomUUID}from"node:crypto";import{performance}from"node:perf_hooks";import{RuntimeCommandError}from"./runtime-command-dispatcher.js";import{ClearConversationUseCase}from"./conversation-clear-use-case.js";import{createSessionModelRefs}from"./openclaw-session-model.js";import{openClawSessionKeysFromList}from"./openclaw-session-key-resolution.js";async function modelSwitchTimingSpan(e,t,i){const s=performance.now();let n="succeeded";try{return await i()}catch(e){throw n="failed",e}finally{e&&process.stderr.write(`[MODEL_SWITCH_TIMING] component=runtime operationId=${e} stage=${t} outcome=${n} durationMs=${(performance.now()-s).toFixed(1)}\n`)}}export class RuntimeSessionControlService{clearRuntime;fallback;activeRuns;constructor(e,t,i){this.clearRuntime=e,this.fallback=t,this.activeRuns=i}async execute(e,t,i){const s=e;if("session.clear"===s.name){if(!i.historyBoundary)throw new RuntimeCommandError("INVALID_PARAMS",`${i.origin} clear attempt lacks its history boundary`);const e=s.context.conversation;return await new ClearConversationUseCase(i.historyBoundary,this.clearRuntime).execute({operationId:s.context.operationId,conversationId:e.runtimeConversationUid,runtimeSessionKey:e.runtimeSessionKey,runtimeEpoch:s.context.dispatchEpoch})}if("session.cancel"===s.name){if(!this.activeRuns)throw new RuntimeCommandError("INVALID_PARAMS","session.cancel active-run authority is not configured");const e=s;return await this.activeRuns.cancelExact({runtimeConversationUid:e.context.conversation.runtimeConversationUid,runtimeSessionKey:e.context.conversation.runtimeSessionKey,historyGeneration:e.context.historyGeneration,targetMessageId:e.params.targetMessageId}),{}}if(!this.fallback)throw new Error(`session command delegate is not configured: ${s.name}`);return await this.fallback.execute(s,t,i)}async projectCommitted(e,t,i){return await(this.fallback?.projectCommitted?.(e,t,i))}}export class OpenClawSessionMetadataService{metadata;constructor(e){this.metadata="function"==typeof e?new OpenClawGatewaySessionMetadataPort(e):e}async execute(e,t,i){const s=e,n=s.context.conversation.runtimeSessionKey,o={lease:t,attempt:i};switch(s.name){case"session.load":return await this.metadata.load(n,o);case"session.rename":{const e=s.params.title.slice(0,64);return await this.metadata.rename(n,e,o)}case"session.delete":return await this.metadata.delete(n,o);case"session.setMode":{const e=s.params.mode;return await this.metadata.setMode(n,e,o)}case"session.setModel":{const e=s.params.modelOverrideId;if(null!==e&&("string"!=typeof e||0===e.length||e.trim()!==e))throw new RuntimeCommandError("INVALID_PARAMS","modelOverrideId must be a non-empty string or null");const t=null===e?await modelSwitchTimingSpan(i.operationId,"resolve_agent_default_model",async()=>await this.metadata.resolveAgentDefaultModel(n,o)):void 0;if(null===e&&!t)throw new RuntimeCommandError("AGENT_DEFAULT_MODEL_NOT_CONFIGURED","agent default model is not configured");return await modelSwitchTimingSpan(i.operationId,"metadata_set_model",async()=>await this.metadata.setModel(n,e,t??void 0,o))}}throw new RuntimeCommandError("INVALID_PARAMS","unsupported session metadata command")}async projectCommitted(e,t,i){if("session.setModel"!==e.name)return;const s=e,n=t;if(this.metadata.projectCommittedSetModel&&await this.metadata.projectCommittedSetModel(s.context.conversation.runtimeSessionKey,n),"service"===i?.origin){if(!i.sessionModelProjection)throw new Error("Message Service session model projection is unavailable");return Object.freeze({state:"pending",revision:"0"})}if(!this.metadata.projectCommittedSetModel)throw new Error("session metadata projection is unavailable")}}export class OpenClawGatewaySessionMetadataPort{getGateway;projectModel;liveSessionKeys;modelMutations;constructor(e,t,i,s){this.getGateway=e,this.projectModel=t,this.liveSessionKeys=i,this.modelMutations=s}modelRefs(){return createSessionModelRefs()}async load(e,t){const i=await this.requireExistingOpenClawKey(e,t);return await this.gateway().request("sessions.resolve",{sessionKey:i}),{loaded:!0}}async rename(e,t,i){const s=await this.requireExistingOpenClawStoreKey(e,i);return await this.gateway().request("sessions.patch",{key:s,label:t}),{title:t}}async delete(e,t){const i=await this.requireExistingOpenClawStoreKey(e,t);return await this.gateway().request("sessions.delete",{key:i}),{deleted:!0}}async setMode(e,t,i){const s=openClawSessionModePatch(t),n=await this.requireExistingOpenClawStoreKey(e,i);if(!isAuthoritativeSetModeAck(await this.gateway().request("sessions.patch",{key:n,...s}),n,s))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact target and effective mode");return{mode:t}}async resolveAgentDefaultModel(e,t){const i=runtimeAgentId(this.liveSessionKeys?(await this.resolveSetModelKey(e,t)).key:await this.requireExistingOpenClawKey(e,t)),s=await this.gateway().request("agents.list",{}),n=s?.agents?.find(e=>e.id===i),o=n?.defaultModel??n?.model;if("string"!=typeof o||!o.trim()||o.trim()!==o)return null;const a=this.modelRefs().toPlatform(o),r=a.indexOf("/");return{modelId:a,...r>0?{modelProvider:a.slice(0,r)}:{}}}async setModel(e,t,i,s){const n=null===t?null:this.modelRefs().toOpenClaw(t),o=s?.attempt.operationId;let a=await modelSwitchTimingSpan(o,"resolve_set_model_key",async()=>await this.resolveSetModelKey(e,s));const r=await(this.modelMutations?.acquireInternal({sessionKey:a.key,label:"session model mutation"}));try{if(r){const t=await this.resolveSetModelKey(e,s);if(t.key!==r.sessionKey)throw new RuntimeCommandError("OUTCOME_UNKNOWN","model target changed while waiting for its physical session gate");a=t}const l=async()=>await modelSwitchTimingSpan(o,"openclaw_sessions_patch",async()=>await this.gateway().request("sessions.patch",{key:a.key,model:n,mustExist:!a.materialized}));let d;try{d=await l()}catch(t){if(a.materialized||!isMissingOpenClawStoreSession(t,a.key))throw t;a=await modelSwitchTimingSpan(o,"materialize_set_model_key",async()=>await this.materializeSetModelKey(e,a.key,s)),d=await l()}const{key:c,materialized:m}=a,u=resolveModelPatch(d,c,t,this.modelRefs()),h=u.effectiveModelId;if(null===t&&(!i||h!==i.modelId))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the prevalidated agent default");if(m){const e=await modelSwitchTimingSpan(o,"openclaw_sessions_list_post_materialize",async()=>await this.gateway().request("sessions.list",{includeDerivedTitles:!0}));if(!openClawSessionKeysFromList(e).has(c))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch acknowledged a model-intent session that is absent from the authoritative store");if(!this.liveSessionKeys?.registerMaterializedModelKey)throw new RuntimeCommandError("OUTCOME_UNKNOWN","model-intent session registration authority is unavailable");this.liveSessionKeys.registerMaterializedModelKey(c)}return u}finally{this.modelMutations?.releaseBeforeRuntime(r)}}async prepareNativeModel(e,t,i,s){await i();const n=void 0===t?null:this.modelRefs().toOpenClaw(t),o=void 0===s?void 0:openClawSessionModePatch(s),a=await this.gateway().request("sessions.patch",{key:e,model:n,...o});await i();const r=a;if(!0!==r?.ok||r.key!==e)throw new RuntimeCommandError("OUTCOME_UNKNOWN","native model patch did not acknowledge the exact qualified session");if(o&&!isAuthoritativeSetModeAck(a,e,o))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact target and effective mode");return resolveModelPatch(a,e,t??null,this.modelRefs())}async projectCommittedSetModel(e,t){if(!this.projectModel)throw new Error("session metadata projection is unavailable");const i=await this.requireExistingOpenClawKey(e);await this.projectModel(i,t)}async requireExistingOpenClawKey(e,t){if(await(this.liveSessionKeys?.waitForHydration?.()),!this.liveSessionKeys)return e;try{return this.liveSessionKeys.resolveLiveKey(e)}catch(i){if(!t||!isMissingLiveSession(i)||!this.liveSessionKeys.reconcileMissingLiveKey)throw i;return await this.liveSessionKeys.reconcileMissingLiveKey(e,t),this.liveSessionKeys.resolveLiveKey(e)}}async requireExistingOpenClawStoreKey(e,t){const i=await this.requireExistingOpenClawKey(e,t),s=await this.gateway().request("sessions.list",{includeDerivedTitles:!0});if(!openClawSessionKeysFromList(s).has(i))throw new RuntimeCommandError("INVALID_PARAMS",`OpenClaw session key does not exist (refusing sessions.patch upsert): ${i}`);return i}async resolveSetModelKey(e,t){let i;const s="service"===t?.attempt.origin&&void 0!==t.attempt.verifiedMessageGrant;try{i=await this.requireExistingOpenClawKey(e,t)}catch(e){if(!(s&&t&&isMissingLiveSession(e)&&this.liveSessionKeys?.materializeMissingModelKey&&this.liveSessionKeys.registerMaterializedModelKey))throw e}return i?{key:i,materialized:!1}:await this.materializeSetModelKey(e,void 0,t)}async materializeSetModelKey(e,t,i){if(!("service"===i?.attempt.origin&&void 0!==i.attempt.verifiedMessageGrant&&i&&this.liveSessionKeys?.materializeMissingModelKey&&this.liveSessionKeys.registerMaterializedModelKey)){throw new RuntimeCommandError("INVALID_PARAMS",`OpenClaw session key does not exist (refusing sessions.patch upsert): ${t??e}`)}const s=await this.liveSessionKeys.materializeMissingModelKey(e,i);if(t&&s!==t)throw new RuntimeCommandError("INVALID_PARAMS","verified model-intent key conflicts with the live local session");return{key:s,materialized:!0}}gateway(){const e=this.getGateway();if(!e?.isConnected)throw new RuntimeCommandError("GATEWAY_NOT_CONNECTED","Gateway not connected");return e}}function isMissingLiveSession(e){return e instanceof RuntimeCommandError&&"INVALID_PARAMS"===e.code&&e.message.startsWith("no live local session")}function isMissingOpenClawStoreSession(e,t){return e instanceof Error&&e.message===`No session found: ${t}`}function resolveModelPatch(e,t,i,s){const n=null===i?null:s.toOpenClaw(i);if(!isAuthoritativeSetModelAck(e,t,n,i))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact existing session and effective model");const o=e.resolved.model,a=s.toPlatform(o);if(null!==i&&a!==i&&o!==n)throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the requested override");return{...null===i?{}:{modelOverrideId:i},effectiveModelId:a,...e.resolved.modelProvider?{modelProvider:e.resolved.modelProvider}:{}}}function runtimeAgentId(e){const t=e.split(":");return"agent"===t[0]&&t[1]?.trim()?t[1]:"main"}export function openClawSessionModePatch(e){const t="verbose"===e||"detailed"===e?{verboseLevel:"full"}:"reasoning"===e||"thinking"===e?{reasoningLevel:"stream"}:"concise"===e||"default"===e?{verboseLevel:"default"}:null;if(!t)throw new RuntimeCommandError("INVALID_PARAMS",`unsupported session mode: ${e}`);return t}function isAuthoritativeSetModeAck(e,t,i){if(!e||"object"!=typeof e||Array.isArray(e))return!1;const s=e;if(!0!==s.ok||s.key!==t||!s.entry||"object"!=typeof s.entry||Array.isArray(s.entry))return!1;const n=s.entry;return"verboseLevel"in i?n.verboseLevel===i.verboseLevel:n.reasoningLevel===i.reasoningLevel}function isAuthoritativeSetModelAck(e,t,i,s){if(!e||"object"!=typeof e||Array.isArray(e))return!1;const n=e;if("ok"in n&&!0!==n.ok)return!1;if("key"in n&&n.key!==t)return!1;const o=n.resolved;if(!o||"object"!=typeof o||Array.isArray(o))return!1;const a=o.model;return"string"==typeof a&&0!==a.length&&a.trim()===a&&(null!==s||null===i)}export class LocalConversationHistoryBoundary{onCommit;kind="local";intents=new Map;convergence=new Map;generations=new Map;constructor(e){this.onCommit=e}currentGeneration(e){return String(this.generations.get(e)??0n)}async prepare(e){const t=this.intents.get(e.operationId);if(t)return t;const i=(new Date).toISOString(),s=this.generations.get(e.conversationId)??0n,n={intentId:randomUUID(),operationId:e.operationId,conversationId:e.conversationId,state:"prepared",runtimeEpoch:e.runtimeEpoch,fromGeneration:String(s),toGeneration:String(s+1n),boundaryOffset:"0",version:"1",createdAt:i,updatedAt:i};return this.intents.set(e.operationId,n),n}async markResetting(e,t){return this.assertState(e,"prepared"),this.convergence.set(e.operationId,t),this.transition(e,"resetting")}async loadRunConvergence(e){const t=this.convergence.get(e.operationId);if(!t)throw new Error("local clear convergence receipt missing");return t}async markResetDone(e){return this.assertState(e,"resetting"),this.transition(e,"reset_done")}async commit(e){return this.assertState(e,"reset_done"),await(this.onCommit?.(e.conversationId)),this.generations.set(e.conversationId,BigInt(e.toGeneration)),this.transition(e,"committed")}async abortPrepared(e){this.assertState(e,"prepared"),this.transition(e,"aborted")}transition(e,t){const i={...e,state:t,version:String(BigInt(e.version)+1n),updatedAt:(new Date).toISOString()};return this.intents.set(e.operationId,i),i}assertState(e,t){const i=this.intents.get(e.operationId);if(!i||i.version!==e.version||i.state!==t)throw new Error(`local clear transition fenced: expected ${t}`)}}
|