export type Brand = T & { readonly __brand: Name }; export type UserId = Brand; export type HotelId = Brand; export type ConversationId = Brand; export type MessageId = Brand; export type SkillId = Brand; export type TaskId = Brand; export type ExecutionId = Brand; export interface User { id: UserId; name: string; avatar?: string; email?: string; phone?: string; hotels: HotelMembership[]; } export interface HotelMembership { hotelId: HotelId; role: 'owner' | 'manager' | 'staff' | 'viewer'; } export interface Hotel { id: HotelId; name: string; brand?: string; city: string; ota: HotelOTABinding[]; } export interface HotelOTABinding { ota: 'ctrip' | 'meituan' | 'booking' | 'agoda' | 'qunar' | string; externalId: string; enabled: boolean; } export type MessageRole = 'user' | 'assistant' | 'system' | 'tool'; export interface Message { id: MessageId; conversationId: ConversationId; role: MessageRole; blocks: ContentBlock[]; createdAt: number; } export type ContentBlock = | TextBlock | ToolCallBlock | ToolResultBlock | ArtifactBlock | ReasoningBlock; export interface TextBlock { type: 'text'; text: string; } export interface ReasoningBlock { type: 'reasoning'; text: string; } export interface ToolCallBlock { type: 'tool_call'; toolCallId: string; name: string; input: Record; } export interface ToolResultBlock { type: 'tool_result'; toolCallId: string; status: 'success' | 'failed'; output: unknown; error?: KernelError; } export interface ArtifactBlock { type: 'artifact'; artifact: Artifact; } export type Artifact = | { kind: 'markdown'; id: string; title?: string; content: string } | { kind: 'table'; id: string; title?: string; columns: string[]; rows: unknown[][] } | { kind: 'chart'; id: string; title?: string; spec: unknown } | { kind: 'image'; id: string; title?: string; url: string } | { kind: 'file'; id: string; title?: string; url: string; mime: string }; export interface KernelError { code: KernelErrorCode; message: string; retryable: boolean; cause?: unknown; } export type KernelErrorCode = | 'kernel_unavailable' | 'kernel_timeout' | 'kernel_aborted' | 'auth_required' | 'permission_denied' | 'skill_not_found' | 'skill_execution_failed' | 'invalid_input' | 'rate_limited' | 'unknown'; export interface Conversation { id: ConversationId; title: string; hotelId: HotelId; createdAt: number; updatedAt: number; messageCount: number; } export interface CreateConversationInput { hotelId: HotelId; title?: string; } export interface SendMessageInput { conversationId: ConversationId; content: TextBlock | { type: 'invoke_skill'; skillId: SkillId; input: Record }; } export type ConversationStreamEvent = | { type: 'message_start'; message: Pick } | { type: 'text_delta'; messageId: MessageId; delta: string } | { type: 'reasoning_delta'; messageId: MessageId; delta: string } | { type: 'tool_call'; messageId: MessageId; block: ToolCallBlock } | { type: 'tool_result'; messageId: MessageId; block: ToolResultBlock } | { type: 'artifact'; messageId: MessageId; artifact: Artifact } | { type: 'message_complete'; messageId: MessageId; message: Message } | { type: 'error'; error: KernelError }; export interface ConversationPort { list(query?: { hotelId?: HotelId; limit?: number }): Promise; get(id: ConversationId): Promise; create(input: CreateConversationInput): Promise; delete(id: ConversationId): Promise; send(input: SendMessageInput): AsyncIterable; abort(conversationId: ConversationId): Promise; history(conversationId: ConversationId, opts?: { before?: MessageId; limit?: number }): Promise; } export interface Adapter { readonly info: { name: string; kernelVersion: string }; connect(): Promise; disconnect(): Promise; health(): Promise<{ ready: boolean; details?: Record }>; readonly conversation: ConversationPort; } export type AdapterFactory = (config: Config) => Adapter;