| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import type { BackendStopMode, SteeringLease } from '@maka/core/backend-types'; |
| import type { RootExecutionDescriptor } from '@maka/core/runtime-invocation'; |
| import type { MessageContent, SessionEvent } from '@maka/core/events'; |
| import type { StopSessionInput } from './session-manager.js'; |
| |
| export interface RuntimeMessageRunIdentity { |
| readonly sessionId: string; |
| readonly turnId: string; |
| readonly runId: string; |
| } |
| |
| /** Lease bridge owned by the Runtime Host for one live root run. */ |
| export interface RuntimeMessageRunOwner extends RuntimeMessageRunIdentity { |
| pull(): Promise<readonly SteeringLease[]>; |
| ack(leaseIds: readonly string[]): void; |
| nack(leaseIds: readonly string[]): void; |
| /** Ends Runtime access; the Host closes admission at its terminal transition cut. */ |
| release(): void; |
| } |
| |
| /** Process-wide factory. Queue admission and projection remain Host responsibilities. */ |
| export interface RuntimeMessageAuthority { |
| bindRun(identity: RuntimeMessageRunIdentity): RuntimeMessageRunOwner; |
| } |
| |
| export interface RuntimeHostedRootExecutionInput extends RuntimeMessageRunIdentity { |
| readonly userMessageId: string | null; |
| readonly execution: RootExecutionDescriptor; |
| readonly content: MessageContent; |
| /** |
| * First-admission control-plane gate. Existing durable admissions bypass it |
| * so recovery never depends on mutable scheduling state. |
| */ |
| readonly admitExecution?: () => Promise<'executing' | 'cancelled'>; |
| readonly start: (input: { |
| readonly runId: string; |
| readonly userMessageId: string | null; |
| readonly onRunStarted: () => void | Promise<void>; |
| }) => AsyncIterable<SessionEvent>; |
| readonly onEvent?: (event: SessionEvent) => void; |
| readonly onReady?: () => void | Promise<void>; |
| } |
| |
| /** Host-only root lifecycle capability. Embedded compositions must omit it. */ |
| export interface RuntimeHostedRootAuthority extends RuntimeMessageAuthority { |
| executeRoot(input: RuntimeHostedRootExecutionInput): Promise<void>; |
| stopRoot(identity: RuntimeMessageRunIdentity, input?: StopSessionInput): Promise<void>; |
| stopSession(sessionId: string, input?: StopSessionInput): Promise<void>; |
| } |
| |
| export function isRuntimeHostedRootAuthority( |
| authority: RuntimeMessageAuthority | undefined, |
| ): authority is RuntimeHostedRootAuthority { |
| return ( |
| authority !== undefined && |
| 'executeRoot' in authority && |
| typeof authority.executeRoot === 'function' && |
| 'stopRoot' in authority && |
| typeof authority.stopRoot === 'function' && |
| 'stopSession' in authority && |
| typeof authority.stopSession === 'function' |
| ); |
| } |
| |
| export class RuntimeMessageAuthorityInvariantError extends Error { |
| readonly name = 'RuntimeMessageAuthorityInvariantError'; |
| } |
| |
| /** |
| * The id a Root Turn's admitted prompt is durable under. A Root folded from |
| * several queued Messages carries no single Message identity, so the id comes |
| * from the Run instead — one rule, so the run that writes the prompt and the |
| * recovery that rewrites it derive the same id and the store dedupes. |
| */ |
| export function admittedPromptEventId( |
| runId: string, |
| userMessageId: string | null | undefined, |
| ): string { |
| return userMessageId ?? `${runId}-admitted-prompt`; |
| } |
| |
| export class RuntimeHostedRootConflictError extends Error { |
| readonly name = 'RuntimeHostedRootConflictError'; |
| readonly code = 'session_busy'; |
| readonly scope: { readonly kind: 'session'; readonly sessionId: string }; |
| |
| constructor(sessionId: string, message: string) { |
| super(message); |
| this.scope = { kind: 'session', sessionId }; |
| } |
| } |
| |
| export class RuntimeHostedRootUnavailableError extends Error { |
| readonly name = 'RuntimeHostedRootUnavailableError'; |
| readonly code = 'session_unavailable'; |
| readonly scope: { readonly kind: 'session'; readonly sessionId: string }; |
| |
| constructor(sessionId: string, message: string, options: ErrorOptions = {}) { |
| super(message, options); |
| this.scope = { kind: 'session', sessionId }; |
| } |
| } |