/** * Nest dependency-injection tokens for the harness-neutral registry and service. * * String tokens follow the existing Gateway convention (see `memory/memory.tokens.ts`) * and remain valid Nest `InjectionToken`s for `@Inject(...)`. */ import type { HarnessConversationService } from '@mosaicstack/types'; export const HARNESS_REGISTRY = 'HARNESS_REGISTRY' as const; export const HARNESS_SERVICE = 'HARNESS_SERVICE' as const; export type HarnessRegistryToken = typeof HARNESS_REGISTRY; export type HarnessServiceToken = typeof HARNESS_SERVICE; /** * Token for the {@link HarnessConversationService} that {@link HarnessChatRuntime} * depends on. Until Task 14 provides a real implementation, `HarnessModule` binds * the {@link HARNESS_CONVERSATION_SERVICE_UNAVAILABLE} sentinel here, and the * `pi-rpc` router treats that sentinel as a hard, typed startup failure. */ export const HARNESS_CONVERSATION_SERVICE = 'HARNESS_CONVERSATION_SERVICE' as const; export type HarnessConversationServiceToken = typeof HARNESS_CONVERSATION_SERVICE; /** * Explicit "not yet bound" value for {@link HARNESS_CONVERSATION_SERVICE}. It is a * distinct sentinel — never `null`/`undefined` — so an unbound service is an * intentional, checkable state rather than an accidental nil that could read as * "present". Replaced by a real service in Task 14. */ export const HARNESS_CONVERSATION_SERVICE_UNAVAILABLE: unique symbol = Symbol( 'HARNESS_CONVERSATION_SERVICE_UNAVAILABLE', ); /** A binding for {@link HARNESS_CONVERSATION_SERVICE}: a real service or the sentinel. */ export type HarnessConversationServiceBinding = | HarnessConversationService | typeof HARNESS_CONVERSATION_SERVICE_UNAVAILABLE; /** Narrows a binding to a usable service, excluding the unavailable sentinel. */ export function isHarnessConversationServiceAvailable( binding: HarnessConversationServiceBinding, ): binding is HarnessConversationService { return binding !== HARNESS_CONVERSATION_SERVICE_UNAVAILABLE; }