/** * Types for the deployment-scoped (external) session plane. * * Mirrors TORUK Core's wire contract, verified against * TORUK-CORE/packages/server/src/deployments/runtime/sessions/ * external-session.mapper.ts and features/sessions/dtos/response/ * message.output.dto.ts. * * Core is the source of truth for sessions, titles, messages and deletion * state — nothing here is ever synthesized locally. */ /** * Lifecycle state of a session as Core reports it. * * Lowercase on the wire — Core's SessionStatus enum is `active` / `deleted` * (database/entities/Session.ts), verified against a live instance. Widened to * `string` so a status Core adds later still parses rather than failing. */ export type TorukSessionStatus = 'active' | 'deleted' | string; /** A single external session owned by the calling visitor. */ export type TorukSession = { /** Session UUID — the id every other session call is addressed by. */ id: string; /** Client-held conversation key, shared with prediction requests. */ chatId: string; title: string; status: TorukSessionStatus; deploymentId: string; messageCount: number; lastMessagePreview?: string; /** ISO-8601 timestamps as serialized by Core. */ lastActivityAt: string | null; createdAt: string; updatedAt: string; }; /** Paging envelope Core returns for both session and message lists. */ export type TorukPagination = { page: number; limit: number; total: number; totalPages: number; hasNext: boolean; hasPrev: boolean; }; export type TorukSessionList = { items: TorukSession[]; pagination: TorukPagination; }; /** * One persisted chat message. Engine passthrough fields arrive as JSON * strings on the wire and are left exactly as Core sent them — parsing is the * consumer's choice. */ export type TorukSessionMessage = { id: string; /** 'userMessage' | 'apiMessage' as stored by the chat engine. */ role: string; content: string; chatId: string; chatflowId: string; chatType: string; /** ISO-8601. Note: Core names this `createdDate` on messages, not `createdAt`. */ createdDate: string; sourceDocuments?: unknown; usedTools?: unknown; fileAnnotations?: unknown; agentReasoning?: unknown; fileUploads?: unknown; artifacts?: unknown; action?: unknown; memoryType?: string; sessionId?: string; followUpPrompts?: unknown; ttsAudio?: unknown; dynamicUiBlocks?: unknown; }; export type TorukSessionMessageList = { items: TorukSessionMessage[]; pagination: TorukPagination; }; /** * One group of message versions: the alternative continuations that hang off a single forked turn. * * A group is addressed by `forkUserOrdinal`, the 1-based position of the user turn it belongs to, * because that is the only handle a client has that survives the fork — the messages after it are * archived and restored as branches. `current` and `total` are the `n` and `m` of the version * pager; `forkAfterMessageId` is the message the fork hangs off, and null for the first turn. */ export type TorukSessionBranchGroup = { forkAfterMessageId: string | null; forkUserOrdinal: number; total: number; current: number; }; /** Every forked turn in one conversation. Empty when nothing has been edited. */ export type TorukSessionBranches = { groups: TorukSessionBranchGroup[]; }; /** Where the pager landed after a switch. */ export type TorukSessionBranchSwitched = { current: number; total: number; }; /** How many messages the fork archived out of the live conversation. */ export type TorukSessionMessagesTruncated = { deletedCount: number; }; /** What Core returns from DELETE — the session is soft-deleted, not erased. */ export type TorukSessionDeleted = { id: string; status: string; deletedAt: string; }; export type TorukSessionSortBy = 'lastActivityAt' | 'createdAt' | 'title'; export type TorukSessionSortOrder = 'ASC' | 'DESC'; /** Options every session method accepts. */ export type SessionRequestOptions = { /** * Overrides the client-level `deploymentId`. One of the two must be set or * the SDK throws a configuration error before any request is made. */ deploymentId?: string; signal?: AbortSignal; headers?: Record; }; export type CreateSessionInput = SessionRequestOptions & { chatId?: string; /** * The visitor's first message. Core does not store this verbatim: it generates the session * title from it and returns the generated title on the response. Omit it and Core uses * "New Chat". Max 200 chars. */ title?: string; }; export type ListSessionsInput = SessionRequestOptions & { /** 1-based. Core defaults to 1. */ page?: number; /** Core defaults to 20, max 100. */ limit?: number; search?: string; sortBy?: TorukSessionSortBy; sortOrder?: TorukSessionSortOrder; }; export type GetSessionInput = SessionRequestOptions & { sessionId: string; }; export type GetSessionMessagesInput = SessionRequestOptions & { sessionId: string; /** 1-based. Core defaults to 1. */ page?: number; /** Core defaults to 50, max 200. */ limit?: number; }; export type RenameSessionInput = SessionRequestOptions & { sessionId: string; /** Max 100 chars. Core strips angle brackets and trims. */ title: string; }; export type DeleteSessionInput = SessionRequestOptions & { sessionId: string; }; export type ListSessionBranchesInput = SessionRequestOptions & { sessionId: string; }; export type SwitchSessionBranchInput = SessionRequestOptions & { sessionId: string; /** 1-based version to make live. */ branchIndex: number; /** The message the fork hangs off. Omit for a fork at the conversation's first turn. */ forkAfterMessageId?: string | null; }; export type TruncateSessionMessagesInput = SessionRequestOptions & { sessionId: string; /** The message to fork at: it and everything after it are archived as the previous version. */ messageId: string; };