import type { AssistantDatabase } from './assistant-database' import type { DesktopStorageClient } from '../desktop-storage-client' import type { ReviewState } from './supervision-review-store' import { repositoryStorageMethods, type DesktopStorageDomains, type StorageArgs, type StorageMethod, type StorageResult } from '../desktop-storage-contracts' export type Awaitable = T | Promise export type DomainPort = { [K in keyof T]: T[K] extends (...args: infer A) => infer R ? (...args: A) => Awaitable> : never } export type ReviewDomainPort = DomainPort export type StoryDomainPort = DomainPort export type ExperienceDomainPort = DomainPort export type SuggestionDomainPort = DomainPort export type HeartbeatDomainPort = DomainPort> export type SupervisionDomainPort = DomainPort> & { supervisionCandidates(...args: Parameters): Awaitable> initializeSupervisionReview(runId: string, state: ReviewState, signal: AbortSignal): Awaitable resumeSupervisionReview(runId: string, signal: AbortSignal): Awaitable supervisionContext(...args: Parameters): Awaitable> supervisionReviewStore(): Awaitable supervisionStories(): Awaitable supervisionExperiences(): Awaitable supervisionSuggestions(): Awaitable } /** Main-side facades contain only RPC closures, never repository instances. */ export function createSupervisionDomainPorts(storage: Pick) { function repository(domain: D): DomainPort { return Object.fromEntries(repositoryStorageMethods[domain].map(method => [method, (...args: unknown[]) => { const signalIndex = domain === 'review' ? method === 'initialize' ? 2 : method === 'resume' ? 1 : -1 : -1 const signal = signalIndex < 0 ? undefined : args[signalIndex] as AbortSignal | undefined if (signalIndex >= 0) args = args.slice(0, signalIndex) return storage.call(domain, method as StorageMethod, args as StorageArgs>, { signal }) }])) as DomainPort } const review = repository('review'), stories = repository('stories') const experiences = repository('experiences'), suggestions = repository('suggestions') const call = >(method: M, ...args: StorageArgs<'assistant', M>): Promise> => storage.call('assistant', method, args) const supervision: SupervisionDomainPort = { createTask: (...args) => call('createTask', ...args), updateTaskStatus: (...args) => call('updateTaskStatus', ...args), upsertModelUsageCall: (...args) => call('upsertModelUsageCall', ...args), resolveReviewScope: (...args) => call('resolveReviewScope', ...args), reviewSummary: (...args) => call('reviewSummary', ...args), reviewBackground: (...args) => call('reviewBackground', ...args), startSupervisionRun: (...args) => call('startSupervisionRun', ...args), failSupervisionRun: (...args) => call('failSupervisionRun', ...args), noChangeSupervisionRun: (...args) => call('noChangeSupervisionRun', ...args), supervisionCandidates: (...args) => call('listSupervisionCandidates', ...args), saveSupervisionResult: (...args) => call('saveSupervisionResult', ...args), initializeSupervisionReview: (runId, state, signal) => storage.call('review', 'initialize', [runId, state], { signal }), resumeSupervisionReview: (runId, signal) => storage.call('review', 'resume', [runId], { signal }), supervisionContext: (request, signal) => storage.call('assistant', 'supervisionContext', [request], { signal }), supervisionReviewStore: () => review, supervisionStories: () => stories, supervisionExperiences: () => experiences, supervisionSuggestions: () => suggestions } const heartbeat: HeartbeatDomainPort = { listHeartbeatConfigs: (...args) => call('listHeartbeatConfigs', ...args), createHeartbeatConfig: (...args) => call('createHeartbeatConfig', ...args), updateHeartbeatConfig: (...args) => call('updateHeartbeatConfig', ...args), setHeartbeatPaused: (...args) => call('setHeartbeatPaused', ...args), removeHeartbeatConfig: (...args) => call('removeHeartbeatConfig', ...args), listHeartbeatRuns: (...args) => call('listHeartbeatRuns', ...args), listHeartbeatEntries: (...args) => call('listHeartbeatEntries', ...args), claimHeartbeatNow: (...args) => call('claimHeartbeatNow', ...args), claimDueHeartbeats: (...args) => call('claimDueHeartbeats', ...args), getHeartbeatRun: (...args) => call('getHeartbeatRun', ...args), getHeartbeatConfig: (...args) => call('getHeartbeatConfig', ...args), supervisionRunForHeartbeat: (...args) => call('supervisionRunForHeartbeat', ...args), completeHeartbeatTrigger: (...args) => call('completeHeartbeatTrigger', ...args), failHeartbeatRun: (...args) => call('failHeartbeatRun', ...args), setHeartbeatProjection: (...args) => call('setHeartbeatProjection', ...args), markHeartbeatNoChange: (...args) => call('markHeartbeatNoChange', ...args), setHeartbeatSuggestionStatus: (...args) => call('setHeartbeatSuggestionStatus', ...args) } return { supervision, heartbeat, review, stories, experiences, suggestions } }