--- title: Owned types description: The package defines its own structural message types — and the AI SDK's UIMessage satisfies them for free. --- The components read messages through types the package owns, in `@intentface/chat/types` — `ChatMessage`, `MessagePart` and its variants (`TextPart`, `ReasoningPart`, `ToolPart`, …), and `ChatStatus`. The package has **no dependency on the AI SDK**; its only peer is React. ## Structural, not nominal The types are defined so that the AI SDK's `UIMessage` satisfies them structurally — no adapter, no mapping layer. A `UIMessage`'s parts already have the shape `ChatMessage` describes, so you pass your SDK messages straight in and they typecheck. ```ts import type { ChatMessage } from "@intentface/chat/types"; import type { UIMessage } from "ai"; // The app's message type flows into the components unchanged. type AppMessage = UIMessage<{ stopped?: boolean }>; const messages: ChatMessage[] = appMessages; // structurally assignable ``` The app keeps a compile-time assertion that its `UIMessage` still satisfies `ChatMessage`, so an AI SDK upgrade that broke the shape would fail typecheck loudly rather than silently. ## Extend by generic `ChatMessage` takes your metadata and part types as generics, so custom parts and metadata carry through the helpers: ```ts type MyMessage = ChatMessage<{ stopped?: boolean }, MyPart>; ``` ## Not the AI SDK Because the contract is structural, the package works with any source that produces the same shape — a different framework, a raw API, your own store. The AI SDK is the common case, not a requirement, and it never appears in the package's dependency graph.