| 393 | } |
| 394 | |
| 395 | export class RuntimeKernel implements RuntimeKernelLike { |
| 396 | private readonly active = new Map<string, BackendGeneration>(); |
| 397 | private readonly childActive = new Map<string, BackendGeneration>(); |
| 398 | private readonly backendGenerations = new Map<number, BackendGeneration>(); |
| 399 | private readonly backendActivationBuilds = new Map<string, Promise<BackendGeneration>>(); |
| 400 | private readonly stopOperations = new Map<string, StopOperation>(); |
| 401 | private readonly stopAttempts = new Map<string, Promise<void>>(); |
| 402 | private readonly executionClaims = new Map<string, Set<PendingExecutionClaim>>(); |
| 403 | private readonly sessionMutationTails = new Map<string, Promise<void>>(); |
| 404 | private readonly executionClaimStates = new WeakMap< |
| 405 | RuntimeExecutionClaim, |
| 406 | PendingExecutionClaim |
| 407 | >(); |
| 408 | private readonly stopIntents = new Map<string, SessionStopIntent>(); |
| 409 | private readonly historyCompactCoordinator: HistoryCompactCheckpointCoordinator; |
| 410 | private readonly pendingContinuationClaims = new Set<string>(); |
| 411 | private readonly pendingContinuationSessions = new Set<string>(); |
| 412 | private readonly steeringBySession = new Map<string, SessionSteeringState>(); |
| 413 | private readonly backendInvalidations = new Map<string, BackendInvalidationState>(); |
| 414 | private readonly interactionRequestOwners = new Map<string, InteractionRequestOwner>(); |
| 415 | private nextBackendGeneration = 0; |
| 416 | private readonly interactionRuns = new Map<AgentRun, RuntimeInteractionRunBinding>(); |
| 417 | |
| 418 | constructor(private readonly deps: RuntimeKernelDeps) { |
| 419 | if (deps.runStore && !deps.runtimeEventStore) { |
| 420 | throw new Error('RuntimeEventStore is required when AgentRunStore is configured'); |
| 421 | } |
| 422 | this.historyCompactCoordinator = new HistoryCompactCheckpointCoordinator(deps); |
| 423 | } |
| 424 | |
| 425 | private async runBackendActivation<T>(operation: () => Promise<T> | T): Promise<T> { |
| 426 | return await (this.deps.runBackendActivation?.(operation) ?? operation()); |
| 427 | } |
| 428 | |
| 429 | claimExecution(sessionId: string): RuntimeExecutionClaim { |
| 430 | if (this.stopIntents.has(sessionId)) { |
| 431 | throw new Error(`Session ${sessionId} is stopping and cannot admit a new execution`); |
| 432 | } |
| 433 | let resolveSettled!: () => void; |
| 434 | let rejectSettled!: (error: unknown) => void; |
| 435 | const settled = new Promise<void>((resolve, reject) => { |
| 436 | resolveSettled = resolve; |
| 437 | rejectSettled = reject; |
| 438 | }); |
| 439 | // A failed claim may have no concurrent stop subscriber; stop still observes this same promise. |
| 440 | void settled.catch(() => undefined); |
| 441 | const abortController = new AbortController(); |
| 442 | const cancellation = new RuntimeExecutionCancellation(sessionId); |
| 443 | const handle: RuntimeExecutionClaim = { |
| 444 | sessionId, |
| 445 | stopSignal: abortController.signal, |
| 446 | isStopRequested: () => state.stopIntent !== undefined, |
| 447 | release: () => this.releaseExecutionClaim(state), |
| 448 | }; |
| 449 | const state: PendingExecutionClaim = { |
| 450 | handle, |
| 451 | sessionId, |
| 452 | abortController, |
nothing calls this directly
no outgoing calls
no test coverage detected