beeos-claw 0.6.51-staging.2 → 0.6.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID}from"node:crypto";import{execFile}from"node:child_process";import{link,mkdir,open,readFile,readdir,rename,rm,stat,unlink}from"node:fs/promises";import{hostname}from"node:os";import path from"node:path";import{performance}from"node:perf_hooks";import{promisify}from"node:util";class CreatorFencedError extends Error{}
|
|
1
|
+
import{randomUUID}from"node:crypto";import{execFile}from"node:child_process";import{link,mkdir,open,readFile,readdir,rename,rm,stat,unlink}from"node:fs/promises";import{hostname}from"node:os";import path from"node:path";import{performance}from"node:perf_hooks";import{promisify}from"node:util";class CreatorFencedError extends Error{}const execFileAsync=promisify(execFile),delay=(t,e)=>new Promise((r,a)=>{if(e?.aborted)return void a(abortError());const o=setTimeout(function(){n(),r()},t),i=()=>{clearTimeout(o),n(),a(abortError())};function n(){e?.removeEventListener("abort",i)}e?.addEventListener("abort",i,{once:!0})});export async function withOwnedDirectoryLock(t,e,r={}){const a=await acquireOwnedDirectoryLock(t,r);try{const t=await e(a);return await a.assertOwned(),t}finally{await a.release()}}export async function acquireOwnedDirectoryLock(t,e={}){const r=positive(e.ttlMs??2e3,"lock ttl"),a=positive(e.heartbeatMs??Math.max(25,Math.floor(r/3)),"heartbeat"),o=positive(e.acquireTimeoutMs??3e4,"acquire timeout"),i=performance.now()+o,n=e.now??Date.now,c=e.random??Math.random,s=e.ownerIdentity??{pid:process.pid,hostname:hostname(),processStartIdentity:await readProcessStartIdentity(process.pid)??""};if(!s.processStartIdentity)throw new Error("cannot establish process-start identity for local lock owner");const w=e.observeProcess??observeLocalProcess;await mkdir(path.dirname(t),{recursive:!0,mode:448});let l=0;const d=async()=>{if(e.signal?.aborted)throw abortError();const r=i-performance.now();if(r<=0)throw new Error(`timed out acquiring lock ${t}`);const a=c();if(!Number.isFinite(a)||a<0||a>=1)throw new Error("lock retry random source must return a value in [0, 1)");const o=Math.min(100,5*2**Math.min(l,5));l+=1;const n=Math.max(1,Math.floor(a*o));await delay(Math.min(n,Math.max(1,Math.ceil(r))),e.signal)};for(;;){if(e.signal?.aborted)throw abortError();const o=randomUUID();try{await mkdir(t,{mode:448});const i=path.join(t,"owner.json"),c=await open(t,"r"),w=(await c.stat()).ino,l=path.join(t,`.owner.${o}.${randomUUID()}.initial`);let d,h,f,y;try{if((await stat(t)).ino!==w)throw new CreatorFencedError("owned directory lock creator was fenced before publication");if(d=await open(l,"wx",384),(await stat(t)).ino!==w)throw new CreatorFencedError("owned directory lock creator was fenced after binding its initial file")}catch(e){const r=await stat(t).then(t=>t.ino===w,()=>!1);if(await(d?.close().catch(()=>{})),await unlink(l).catch(()=>{}),await c.close().catch(()=>{}),!r)throw new CreatorFencedError("owned directory lock creator lost its directory while binding");throw e}try{h=await reserveEpoch(t,await(e.epochFloor?.())??0n)}catch(t){throw await(d?.close().catch(()=>{})),await unlink(l).catch(()=>{}),await c.close().catch(()=>{}),t}let p,u=n()+r,m=!1,k=Promise.resolve();const E=async()=>{const t=await open(i,"r");let e,r;try{e=parseOwner(await t.readFile("utf8")),r=(await t.stat()).ino}finally{await t.close()}if(e.token!==o||e.epoch!==h||r!==y)throw new Error("owned directory lock was fenced by a successor epoch");return e},b=async()=>{if(m)throw new Error("owned directory lock was released");if(p)throw p;const t=await E();if(n()>=t.expiresAtMs)throw new Error("owned directory lock lease expired")},v=async t=>{const e=k.catch(()=>{}).then(t);return k=e.catch(()=>{}),await e},I=async(r=!0)=>{const a=await E();if(r&&n()>=a.expiresAtMs)throw new Error("owned directory lock lease expired");const l=path.join(t,`.owner.${o}.${randomUUID()}.tmp`),d=await open(l,"wx",384);let p=!1;try{if((await stat(t)).ino!==w)throw new Error("owned directory lock was fenced before heartbeat publication");if(await d.writeFile(JSON.stringify({token:o,epoch:h,...s,expiresAtMs:u}),"utf8"),await d.sync(),await(e.beforeOwnerRename?.("heartbeat")),(await stat(t)).ino!==w)throw new Error("owned directory lock was fenced by a successor directory");const r=(await d.stat()).ino;await rename(l,i),p=!0;const a=f;f=d,y=r;try{await c.sync()}catch(t){throw await d.close().catch(()=>{}),f=void 0,await(a?.close().catch(()=>{})),t}await(a?.close())}finally{p||(await d.close().catch(()=>{}),await rm(l,{force:!0}).catch(()=>{}))}};try{if(await d.writeFile(JSON.stringify({token:o,epoch:h,...s,expiresAtMs:u}),"utf8"),await d.sync(),await(e.beforeOwnerRename?.("initial")),(await stat(t)).ino!==w)throw new CreatorFencedError("owned directory lock creator was fenced by a successor directory");await link(l,i),await unlink(l),await c.sync(),f=d,y=(await d.stat()).ino,d=void 0}catch(e){const r=await stat(t).then(t=>t.ino===w,()=>!1);if(await(d?.close().catch(()=>{})),await unlink(l).catch(()=>{}),await c.close().catch(()=>{}),!r)throw new CreatorFencedError("owned directory lock creator lost its directory before publication");throw e}const x=async()=>await v(async()=>{if(m||p)throw p??new Error("owned directory lock was released");await b(),u=n()+r,await I(!0)});let F=!1;const M=setInterval(()=>{m||p||F||(F=!0,x().catch(t=>{p=t instanceof Error?t:new Error("lock heartbeat failed")}).finally(()=>{F=!1}))},a);return M.unref?.(),{epoch:h,assertOwned:()=>v(b),heartbeat:x,release:async()=>{clearInterval(M),await v(async()=>{if(!m){try{await E(),u=n()-1,await I(!1)}catch{}m=!0,await(f?.close().catch(()=>{})),f=void 0,await c.close().catch(()=>{})}})}}}catch(e){if(e instanceof CreatorFencedError){await d();continue}const a=e.code;if("ENOENT"===a){await d();continue}if("EEXIST"!==a)throw e;const o=await reclaimable(t,s,w,n(),r);if(o){const e=`${t}.expired.${randomUUID()}`;try{if(await rename(t,e),await verifyReclaimProof(e,o,s,w,n(),r)){await rm(e,{recursive:!0,force:!0,maxRetries:8,retryDelay:1}),await syncDirectory(path.dirname(t));continue}await rename(e,t).catch(()=>{})}catch(t){if("ENOENT"!==t.code)throw t}}await d()}}}async function reclaimable(t,e,r,a,o){let i;try{const e=await open(path.join(t,"owner.json"),"r");let r,a;try{r=parseOwner(await e.readFile("utf8")),a=(await e.stat()).ino}finally{await e.close()}i={owner:r,inode:a}}catch{try{const e=await stat(t);return e.mtimeMs+o<=a?{kind:"directory",inode:e.ino,mtimeMs:e.mtimeMs}:null}catch{return null}}return i.owner.expiresAtMs<=a||i.owner.hostname===e.hostname&&await isProvenDead(i.owner,r)?{kind:"owner",...i}:null}async function verifyReclaimProof(t,e,r,a,o,i){try{const n=await reclaimable(t,r,a,o,i);return!(!n||n.kind!==e.kind)&&("directory"===e.kind?"directory"===n.kind&&n.inode===e.inode:"owner"===n.kind&&n.owner.token===e.owner.token&&n.owner.epoch===e.owner.epoch)}catch{return!1}}async function reserveEpoch(t,e){const r=`${t}.epochs`;await mkdir(r,{recursive:!0,mode:448});let a=0n;try{const e=(await readFile(`${t}.epoch`,"utf8")).trim();if(!/^(0|[1-9][0-9]*)$/.test(e))throw new Error("lock epoch is corrupt");a=BigInt(e)}catch(t){if("ENOENT"!==t.code)throw t}for(;;){const o=await readdir(r),i=`${[e,a,o.reduce((t,e)=>/^(0|[1-9][0-9]*)$/.test(e)&&BigInt(e)>t?BigInt(e):t,0n)].reduce((t,e)=>e>t?e:t,0n)+1n}`;try{const e=await open(path.join(r,i),"wx",384);try{await e.writeFile(`${i}\n`,"utf8"),await e.sync()}finally{await e.close()}return await Promise.all(o.filter(t=>/^(0|[1-9][0-9]*)$/.test(t)&&BigInt(t)<BigInt(i)).map(t=>unlink(path.join(r,t)).catch(t=>{if("ENOENT"!==t.code)throw t}))),await syncDirectory(r),await syncDirectory(path.dirname(t)),i}catch(t){if("EEXIST"!==t.code)throw t}}}function parseOwner(t){const e=JSON.parse(t);if(!e||"string"!=typeof e.token||!/^[1-9][0-9]*$/.test(e.epoch)||!Number.isSafeInteger(e.pid)||e.pid<=0||"string"!=typeof e.hostname||!e.hostname||"string"!=typeof e.processStartIdentity||!e.processStartIdentity||!Number.isFinite(e.expiresAtMs))throw new Error("lock owner is invalid");return e}async function isProvenDead(t,e){const r=await e(t.pid);return!r.alive||void 0!==r.processStartIdentity&&r.processStartIdentity!==t.processStartIdentity}async function observeLocalProcess(t){try{process.kill(t,0)}catch(t){return"ESRCH"===t.code?{alive:!1}:{alive:!0}}const e=await readProcessStartIdentity(t);return{alive:!0,...e?{processStartIdentity:e}:{}}}async function readProcessStartIdentity(t){if("linux"===process.platform)try{const e=await readFile(`/proc/${t}/stat`,"utf8"),r=e.slice(e.lastIndexOf(")")+2).trim().split(/\s+/)[19];return r?`linux:${r}`:null}catch{return null}if("darwin"===process.platform)try{const{stdout:e}=await execFileAsync("/bin/ps",["-o","lstart=","-p",String(t)]),r=e.trim();return r?`darwin:${r}`:null}catch{return null}return null}function positive(t,e){if(!Number.isSafeInteger(t)||t<=0)throw new Error(`${e} must be a positive integer`);return t}function abortError(){const t=new Error("lock acquisition aborted");return t.name="AbortError",t}async function syncDirectory(t){const e=await open(t,"r");try{await e.sync()}finally{await e.close()}}
|
|
@@ -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.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{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;export class RuntimeCommandJournalConflictError extends Error{constructor(e){super(e),this.name="RuntimeCommandJournalConflictError"}}export class FileRuntimeCommandJournal{file;retentionMs;now;publication;segments;maintenance;forceCheckpointRequested=!1;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 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;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);return t.mark("publish-delta"),n=checkpointDue(r,1,d),s},{...this.publication.lockOptions,epochFloor:()=>this.segments.authorityFloor()})}finally{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;do{const t=this.forceCheckpointRequested;this.forceCheckpointRequested=!1,e+=await this.runMaintenance(t)}while(this.forceCheckpointRequested);return e})().finally(()=>{this.maintenance===e&&(this.maintenance=void 0)});return this.maintenance=e,e}async runMaintenance(e){const t=createRuntimeAppendTimingRecorder("journal.checkpoint",{file:this.file});try{return await withOwnedDirectoryLock(`${this.file}.lock`,async n=>{t.mark("lock");const o=await this.readState();if(t.mark("read"),!e&&!checkpointDue(o))return t.mark("not-due"),0;const r=o.document,i=this.now()-this.retentionMs,a=r.records.length;r.records=r.records.filter(e=>"prepared"===e.phase||"started"===e.phase||Date.parse(e.updatedAt)>=i);const s=r.cancellations.length;r.cancellations=r.cancellations.filter(e=>Date.parse(e.observedAt)>=i);const c=a-r.records.length+s-r.cancellations.length,d=documentValues(r);return await(this.publication.beforePublish?.(n.epoch)),t.mark("before-publish"),await n.assertOwned(),t.mark("assert-owned"),await this.segments.checkpointSnapshot(n.epoch,d,o.authorityFloor),t.mark("publish-snapshot"),await n.assertOwned(),await this.segments.prune(),t.mark("prune"),c},{...this.publication.lockOptions,epochFloor:()=>this.segments.authorityFloor()})}finally{t.finish(e?"forced":"scheduled")}}}function checkpointDue(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||r>0&&s>0&&o-s>=6e5}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 +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{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;constructor(e,t,i){this.getGateway=e,this.projectModel=t,this.liveSessionKeys=i}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="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}),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 r=toPlatformModelId(o),a=r.indexOf("/");return{modelId:r,...a>0?{modelProvider:r.slice(0,a)}:{}}}async setModel(e,t,i,s){const n=null===t?null:toOpenClawSessionModel(t),o=s?.attempt.operationId;let r=await modelSwitchTimingSpan(o,"resolve_set_model_key",async()=>await this.resolveSetModelKey(e,s));const a=async()=>await modelSwitchTimingSpan(o,"openclaw_sessions_patch",async()=>await this.gateway().request("sessions.patch",{key:r.key,model:n,mustExist:!r.materialized}));let l;try{l=await a()}catch(t){if(r.materialized||!isMissingOpenClawStoreSession(t,r.key))throw t;r=await modelSwitchTimingSpan(o,"materialize_set_model_key",async()=>await this.materializeSetModelKey(e,r.key,s)),l=await a()}const{key:c,materialized:d}=r;if(!isAuthoritativeSetModelAck(l,c,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=toPlatformModelId(m);if(null===t&&(!i||u!==i.modelId))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the prevalidated agent default");if(null!==t&&u!==t&&m!==n)throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the requested override");if(d){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{...null===t?{}:{modelOverrideId:t},effectiveModelId:u,...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 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 runtimeAgentId(e){const t=e.split(":");return"agent"===t[0]&&t[1]?.trim()?t[1]:"main"}function toOpenClawSessionModel(e){return e.startsWith(`${AROUTER_PROVIDER_ID}/`)?e:`${AROUTER_PROVIDER_ID}/${e}`}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;return"string"==typeof r&&0!==r.length&&r.trim()===r&&(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}`)}}
|
|
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{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;constructor(e,t,i){this.getGateway=e,this.projectModel=t,this.liveSessionKeys=i}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="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}),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 r=toPlatformModelId(o),a=r.indexOf("/");return{modelId:r,...a>0?{modelProvider:r.slice(0,a)}:{}}}async setModel(e,t,i,s){const n=null===t?null:toOpenClawSessionModel(t),o=s?.attempt.operationId,{key:r,materialized:a}=await modelSwitchTimingSpan(o,"resolve_set_model_key",async()=>await this.resolveSetModelKey(e,s)),l=await modelSwitchTimingSpan(o,"openclaw_sessions_patch",async()=>await this.gateway().request("sessions.patch",{key:r,model:n}));if(!isAuthoritativeSetModelAck(l,r,n,t))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch did not acknowledge the exact existing session and effective model");const c=l.resolved.model,d=toPlatformModelId(c);if(null===t&&(!i||d!==i.modelId))throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the prevalidated agent default");if(null!==t&&d!==t&&c!==n)throw new RuntimeCommandError("OUTCOME_UNKNOWN","sessions.patch effective model does not match the requested override");if(a){const e=await modelSwitchTimingSpan(o,"openclaw_sessions_list_post_materialize",async()=>await this.gateway().request("sessions.list",{includeDerivedTitles:!0}));if(!openClawSessionKeysFromList(e).has(r))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(r)}return{...null===t?{}:{modelOverrideId:t},effectiveModelId:d,...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 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}if(i){const e=await modelSwitchTimingSpan(t?.attempt.operationId,"openclaw_sessions_list_pre_patch",async()=>await this.gateway().request("sessions.list",{includeDerivedTitles:!0}));if(openClawSessionKeysFromList(e).has(i))return{key:i,materialized:!1}}if(!(s&&t&&this.liveSessionKeys?.materializeMissingModelKey&&this.liveSessionKeys.registerMaterializedModelKey)){throw new RuntimeCommandError("INVALID_PARAMS",`OpenClaw session key does not exist (refusing sessions.patch upsert): ${i??e}`)}const n=await this.liveSessionKeys.materializeMissingModelKey(e,t);if(i&&n!==i)throw new RuntimeCommandError("INVALID_PARAMS","verified model-intent key conflicts with the live local session");return{key:n,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 toOpenClawSessionModel(e){return e.startsWith(`${AROUTER_PROVIDER_ID}/`)?e:`${AROUTER_PROVIDER_ID}/${e}`}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;return"string"==typeof r&&0!==r.length&&r.trim()===r&&(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}`)}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "beeos-claw",
|
|
3
|
-
"version": "0.6.51
|
|
3
|
+
"version": "0.6.51",
|
|
4
4
|
"description": "OpenClaw plugin that bridges the BeeOS platform with the local OpenClaw Gateway, providing file transfer, ACP bridge, and observability.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "BeeOS <dev@beeos.ai>",
|
|
@@ -87,5 +87,5 @@
|
|
|
87
87
|
"fast-uri": ">=3.1.4",
|
|
88
88
|
"brace-expansion": ">=5.0.9"
|
|
89
89
|
},
|
|
90
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "3c8f14a13eb815a0459778de9c5dca901690976c"
|
|
91
91
|
}
|