| import { randomUUID } from 'node:crypto'; |
| import { |
| AgentGraphCoordinator, |
| BackendRegistry, |
| FakeBackend, |
| SessionManager, |
| type RuntimeHostedRootAuthority, |
| } from '@maka/runtime'; |
| import { createAgentGraphControlStore } from '@maka/storage/agent-graph-control-store'; |
| import { openInteractiveArtifactStoreForWrite } from '@maka/storage/artifact-stores'; |
| import { openInteractiveExecutionStoresForWrite } from '@maka/storage/execution-stores'; |
| import { runWithStorageRootLease } from '@maka/storage/root-authority'; |
| import { openInteractiveRuntimePolicyStoresForWrite } from '@maka/storage/runtime-policy-stores'; |
| import { openInteractiveTaskLedgerStoreForWrite } from '@maka/storage/task-ledger-authority'; |
| import { CanonicalSessionProjectionReader } from './canonical-session-projection.js'; |
| import { HostCanonicalPermissionOutcomeReader } from './canonical-permission-outcome-reader.js'; |
| import { HostArtifactCoordinator } from './artifact-coordinator.js'; |
| import type { RuntimeHostComposition, RuntimeHostCompositionContext } from './host-kernel.js'; |
| import { HostInteractionCoordinator } from './interaction-coordinator.js'; |
| import { type HostMessageRootPort, HostMessageCoordinator } from './message-coordinator.js'; |
| import type { DomainOperationHandlerMap } from './operation-dispatcher.js'; |
| import { RootAdmissionOwner } from './root-admission-owner.js'; |
| import { RootTurnCoordinator } from './root-turn-coordinator.js'; |
| import { RuntimePolicyActivationGate } from './runtime-policy-activation-gate.js'; |
| import { HostRuntimePolicyCoordinator } from './runtime-policy-coordinator.js'; |
| import { SessionAdmissionGate } from './session-admission-gate.js'; |
| import { SessionContinuityCoordinator } from './session-continuity-coordinator.js'; |
| import { HostSkillCatalogCoordinator } from './skill-catalog-coordinator.js'; |
| import { SkillCatalogRepository } from './skill-catalog-repository.js'; |
| import { HostTaskLedgerCoordinator } from './task-ledger-coordinator.js'; |
| |
| export async function createExecutionRuntimeHostComposition( |
| context: RuntimeHostCompositionContext, |
| ): Promise<RuntimeHostComposition> { |
| const stores = await openInteractiveExecutionStoresForWrite(context.owner.lease); |
| let graphControlStore: ReturnType<typeof createAgentGraphControlStore> | undefined; |
| try { |
| const runtimePolicyStores = await openInteractiveRuntimePolicyStoresForWrite( |
| context.owner.lease, |
| ); |
| const taskLedgerStore = await openInteractiveTaskLedgerStoreForWrite(context.owner.lease); |
| const openedArtifactStore = await openInteractiveArtifactStoreForWrite(context.owner.lease); |
| await stores.messageReceiptStore.beginHostEpoch(context.hostEpoch); |
| const backends = new BackendRegistry(); |
| backends.register('fake', (backendContext) => new FakeBackend(backendContext)); |
| const runtimePolicyActivation = new RuntimePolicyActivationGate(); |
| const sessionAdmission = new SessionAdmissionGate(); |
| const taskLedger = new HostTaskLedgerCoordinator(taskLedgerStore, sessionAdmission); |
| const openedGraphControlStore = createAgentGraphControlStore( |
| context.owner.capability.canonicalPath, |
| ); |
| graphControlStore = openedGraphControlStore; |
| const skills = new HostSkillCatalogCoordinator( |
| new SkillCatalogRepository({ |
| runWithRoot: (operation) => |
| runWithStorageRootLease(context.owner.lease, 'interactive', 'write', operation), |
| }), |
| ); |
| let rootCoordinator: RootTurnCoordinator | undefined; |
| let continuity: SessionContinuityCoordinator | undefined; |
| let canonicalProjection: CanonicalSessionProjectionReader | undefined; |
| const rootPort: HostMessageRootPort = { |
| readSessionHeader: (sessionId) => |
| requireRootCoordinator(rootCoordinator).readSessionHeader(sessionId), |
| readRootState: (sessionId) => |
| requireRootCoordinator(rootCoordinator).readRootState(sessionId), |
| claimStopFence: (input, commitQueueFence, admission) => |
| requireRootCoordinator(rootCoordinator).claimStopFence(input, commitQueueFence, admission), |
| startFromMessage: (input, admission) => |
| requireRootCoordinator(rootCoordinator).startFromMessage(input, admission), |
| claimStop: (input, commitQueueFence, admission) => |
| requireRootCoordinator(rootCoordinator).claimStop(input, commitQueueFence, admission), |
| }; |
| const messages = new HostMessageCoordinator({ |
| hostEpoch: context.hostEpoch, |
| root: rootPort, |
| durableProof: { |
| readRootTurnSourceMessageReceipt: (sessionId, messageId) => |
| stores.agentRunStore.readRootTurnSourceMessageReceipt(sessionId, messageId), |
| readImmutableSteeringMessageProof: (sessionId, messageId) => |
| stores.runtimeEventStore.readImmutableSteeringMessageProof(sessionId, messageId), |
| }, |
| receipts: stores.messageReceiptStore, |
| sessionAdmission, |
| acquireResidency: context.acquireResidency, |
| requestDrain: context.requestDrain, |
| preflightSessionSnapshot: (sessionId, candidate) => |
| requireCanonicalProjection(canonicalProjection).fitsCandidate(sessionId, candidate), |
| onProjectionChanged: (sessionId) => |
| requireContinuity(continuity).enqueueCanonicalRefresh(sessionId), |
| }); |
| const rootAdmissionOwner = new RootAdmissionOwner(stores.agentRunStore); |
| const canonicalProjectionReader = new CanonicalSessionProjectionReader({ |
| stores, |
| rootAdmissions: rootAdmissionOwner, |
| messages, |
| }); |
| canonicalProjection = canonicalProjectionReader; |
| continuity = new SessionContinuityCoordinator( |
| context.hostEpoch, |
| (sessionId) => canonicalProjectionReader.read(sessionId), |
| sessionAdmission, |
| context.requestDrain, |
| ); |
| const continuityCoordinator = continuity; |
| let poisonFailure: Error | undefined; |
| let draining = false; |
| let recoveryTask: Promise<void> | undefined; |
| let rootCloseTask: Promise<void> | undefined; |
| let closeTask: Promise<void> | undefined; |
| const beginDrain = () => { |
| if (draining) return; |
| draining = true; |
| messages.beginDrain(); |
| interactions.beginDrain(); |
| skills.beginDrain(); |
| }; |
| const interactions = new HostInteractionCoordinator({ |
| store: stores.interactionStore, |
| sessionAdmission, |
| preflightSessionSnapshot: (sessionId, interactionProjection) => |
| canonicalProjectionReader.fitsCandidate(sessionId, { |
| interactions: interactionProjection, |
| }), |
| refreshCanonicalContinuity: (sessionId, admission) => |
| continuityCoordinator.refreshCanonical(sessionId, admission), |
| onPoison: (error) => { |
| if (poisonFailure) return; |
| poisonFailure = error; |
| context.retainUntilProcessExit(); |
| beginDrain(); |
| context.requestDrain(); |
| }, |
| }); |
| const canonicalPermissionOutcomes = new HostCanonicalPermissionOutcomeReader({ |
| store: stores.interactionStore, |
| }); |
| const runtimeAuthority: RuntimeHostedRootAuthority = { |
| bindRun: (identity) => messages.bindRun(identity), |
| executeRoot: (input) => requireRootCoordinator(rootCoordinator).executeRoot(input), |
| stopRoot: (identity, input) => |
| requireRootCoordinator(rootCoordinator).stopRoot(identity, input), |
| stopSession: (sessionId, input) => |
| requireRootCoordinator(rootCoordinator).stopSession(sessionId, input), |
| }; |
| const manager = new SessionManager({ |
| store: stores.sessionStore, |
| runStore: stores.agentRunStore, |
| runtimeEventStore: stores.runtimeEventStore, |
| backends, |
| newId: randomUUID, |
| now: Date.now, |
| runBackendActivation: (operation) => runtimePolicyActivation.runBackendActivation(operation), |
| messageAuthority: runtimeAuthority, |
| hostedAgentGraphExecution: { |
| readAgentGraphIntentClaim: (graphId, intentId) => |
| openedGraphControlStore.readAgentGraphIntentClaim(graphId, intentId), |
| readRootTurnAdmissionIdentity: async (sessionId, turnId) => { |
| const admission = await stores.agentRunStore.readRootTurnAdmission(sessionId, turnId); |
| return admission |
| ? { runId: admission.runId, userMessageId: admission.userMessageId } |
| : undefined; |
| }, |
| }, |
| interactionAuthority: interactions, |
| canonicalPermissionOutcomes, |
| }); |
| const graphCoordinator = new AgentGraphCoordinator({ |
| sessionStore: stores.sessionStore, |
| runStore: stores.agentRunStore, |
| runtimeEventStore: stores.runtimeEventStore, |
| controlStore: openedGraphControlStore, |
| runtime: manager, |
| newId: randomUUID, |
| }); |
| rootCoordinator = new RootTurnCoordinator( |
| manager, |
| stores, |
| sessionAdmission, |
| rootAdmissionOwner, |
| interactions, |
| messages, |
| continuityCoordinator, |
| context.acquireResidency, |
| context.requestDrain, |
| ); |
| const coordinator = rootCoordinator; |
| const runtimePolicy = new HostRuntimePolicyCoordinator( |
| runtimePolicyStores, |
| runtimePolicyActivation, |
| async () => { |
| try { |
| await manager.refreshIdleBackends(); |
| } catch (error) { |
| context.requestDrain(); |
| throw error; |
| } |
| }, |
| ); |
| const artifacts = new HostArtifactCoordinator(openedArtifactStore, context.requestDrain); |
| const handlers = { |
| ...coordinator.handlers, |
| ...messages.handlers, |
| ...interactions.handlers, |
| ...runtimePolicy.handlers, |
| ...continuityCoordinator.handlers, |
| ...taskLedger.handlers, |
| ...artifacts.handlers, |
| ...skills.handlers, |
| } satisfies DomainOperationHandlerMap; |
| const recover = () => { |
| recoveryTask ??= (async () => { |
| await skills.recover(); |
| const sessions = await stores.sessionStore.listForRecovery(); |
| for (const session of sessions) { |
| await stores.runtimeEventStore.repairImmutableSteeringMessageProofsForRecovery( |
| session.id, |
| ); |
| } |
| await coordinator.prepareRecovery(); |
| await openedArtifactStore.recover(); |
| await interactions.recoverPendingAfterHostRestart(); |
| await manager.recoverInterruptedSessionsStrict(stores); |
| await graphCoordinator.recover(); |
| await coordinator.recover(); |
| })(); |
| return recoveryTask; |
| }; |
| const close = () => { |
| closeTask ??= (async () => { |
| beginDrain(); |
| const errors: unknown[] = []; |
| let recovered = false; |
| try { |
| await recover(); |
| recovered = true; |
| } catch (error) { |
| errors.push(error); |
| } |
| try { |
| await graphCoordinator.close(); |
| } catch (error) { |
| errors.push(error); |
| } |
| if (recovered && !poisonFailure) { |
| try { |
| rootCloseTask ??= coordinator.close(); |
| await rootCloseTask; |
| } catch (error) { |
| errors.push(error); |
| } |
| } |
| try { |
| openedGraphControlStore.close(); |
| } catch (error) { |
| errors.push(error); |
| } |
| try { |
| await messages.close(); |
| } catch (error) { |
| errors.push(error); |
| } |
| try { |
| await interactions.close(); |
| } catch (error) { |
| errors.push(error); |
| } |
| try { |
| continuityCoordinator.close(); |
| } catch (error) { |
| errors.push(error); |
| } |
| try { |
| await skills.close(); |
| } catch (error) { |
| errors.push(error); |
| } |
| try { |
| await stores.sessionStore.close?.(); |
| } catch (error) { |
| errors.push(error); |
| } |
| if (poisonFailure && !errors.includes(poisonFailure)) errors.push(poisonFailure); |
| if (errors.length > 0) { |
| throw new AggregateError(errors, 'Unable to close Runtime Host execution composition'); |
| } |
| })(); |
| return closeTask; |
| }; |
| return { |
| handlers, |
| continuity: continuityCoordinator, |
| beginDrain, |
| recover, |
| close, |
| }; |
| } catch (error) { |
| const errors: unknown[] = [error]; |
| try { |
| graphControlStore?.close(); |
| } catch (closeError) { |
| errors.push(closeError); |
| } |
| try { |
| await stores.sessionStore.close?.(); |
| } catch (closeError) { |
| errors.push(closeError); |
| } |
| if (errors.length === 1) throw error; |
| throw new AggregateError(errors, 'Unable to clean up Runtime Host execution composition'); |
| } |
| } |
| |
| function requireRootCoordinator(coordinator: RootTurnCoordinator | undefined): RootTurnCoordinator { |
| if (!coordinator) throw new Error('Runtime Host root coordinator is not composed'); |
| return coordinator; |
| } |
| |
| function requireContinuity( |
| continuity: SessionContinuityCoordinator | undefined, |
| ): SessionContinuityCoordinator { |
| if (!continuity) throw new Error('Runtime Host continuity coordinator is not composed'); |
| return continuity; |
| } |
| |
| function requireCanonicalProjection( |
| projection: CanonicalSessionProjectionReader | undefined, |
| ): CanonicalSessionProjectionReader { |
| if (!projection) throw new Error('Runtime Host canonical projection is not composed'); |
| return projection; |
| } |