import { SmrtObjectOptions } from '@happyvertical/smrt-core'; import { SupportAiRunCollection } from '../models/support-ai-run.js'; import { SupportCase } from '../models/support-case.js'; import { HumanHandoffTrigger } from '../types.js'; import { SupportCaseService } from './support-case-service.js'; /** One compact timeline entry inside a {@link HandoffContextPackage}. */ export interface HandoffTimelineItem { kind: 'interaction' | 'event'; /** ISO-8601 timestamp (the package is embedded in a JSON event payload). */ occurredAt: string; actorKind: string; summary: string; /** Interaction body — the Client's own words travel with the handoff. */ body?: string; } /** One compact AI-run entry inside a {@link HandoffContextPackage}. */ export interface HandoffAiRunSummary { phase: string; outcome: string; confidence: number | null; classification: Record; error: string | null; } /** * The lossless context a Human Handoff transfers (FR-28b): the case's current * state plus the merged timeline and every prior automated-work audit row. * This is what the assigned Support Specialist receives — the Client never * repeats themselves. */ export interface HandoffContextPackage { caseNumber: string; subject: string; status: string; severity: string; category: string; clientProfileId: string | null; projectId: string | null; planId: string | null; timeline: HandoffTimelineItem[]; aiRuns: HandoffAiRunSummary[]; } /** * The routing seam (#1929): pick the Support Specialist for a handed-off * case. Return `null` to leave the case in the queue for manual assignment. */ export type SpecialistRouter = (supportCase: SupportCase, context: { trigger: HumanHandoffTrigger; }) => Promise<{ specialistId: string; rationale?: Record; } | null>; /** Options for {@link HumanHandoffService.create}. */ export interface HumanHandoffServiceOptions extends SmrtObjectOptions { /** Routing seam; omitted → handed-off cases queue for manual assignment. */ assignSpecialist?: SpecialistRouter; } /** Input for one {@link HumanHandoffService.handoff} call. */ export interface HumanHandoffInput { trigger: HumanHandoffTrigger; /** Free-form context for the audit event (why the trigger fired). */ note?: string; /** The requesting Client profile, for `client_request` triggers. */ requestedByProfileId?: string | null; } /** Result of one {@link HumanHandoffService.handoff} call. */ export interface HumanHandoffResult { supportCase: SupportCase; /** True when an earlier handoff was still active (no-repeat guarantee). */ alreadyActive: boolean; } /** * The Human Handoff engine. Construct with {@link HumanHandoffService.create}. */ export declare class HumanHandoffService { readonly caseService: SupportCaseService; readonly aiRuns: SupportAiRunCollection; private readonly assignSpecialist?; protected constructor(deps: { caseService: SupportCaseService; aiRuns: SupportAiRunCollection; assignSpecialist?: SpecialistRouter; }); static create(options: HumanHandoffServiceOptions): Promise; /** * Assemble the lossless context package for a case: current state, the * merged interaction/event timeline, and every prior AI run (FR-28b). */ buildContextPackage(caseId: string): Promise; /** * Hand the case to a human: enforce the no-repeat guarantee, stamp * `metadata.activeHandoff`, record the `handoff` audit event carrying the * full context package, then route via the `assignSpecialist` seam (or * queue the case as `triaged` when unrouted). */ handoff(caseRef: SupportCase | string, input: HumanHandoffInput): Promise; /** * Clear the active-handoff flag so a later trigger can hand off again. * Apps call this when the handoff concludes (assignment accepted or the * case resolves); a resolve-then-reopen also invalidates the flag * automatically inside {@link handoff}. */ releaseHandoff(caseRef: SupportCase | string): Promise; /** * Whether a handoff is still pending on the case. A flag survives only * while the case stays open; a resolve-and-reopen since the flag was set * makes it stale (the new conversation may hand off afresh). */ private isHandoffActive; /** The persisted id of a saved case. */ private caseIdOf; } export default HumanHandoffService; //# sourceMappingURL=human-handoff-service.d.ts.map