UIX
Deepractice · Deepractice/UIX
UIX provides an AI-to-UI protocol and conversion engine to normalize AI output into a consistent format for any UI framework.
AI-to-UI IR Protocol Layer — The Last Mile from AI to Human. Includes Lucid UI Skill for professional AI-generated interfaces.
Preview
What you can do with it
- Build a chat interface that can display AI outputs from different LLM providers consistently.
- Develop UI components that automatically adapt to various AI-generated content formats.
- Ensure UI designs generated by AI agents adhere to a unified design system.
Safety check
No risky patterns found in the files we scanned.
Automated scan of the repo files. Always review code you run.
From the README
UIX
<strong>The Last Mile from AI to Human</strong>
AI-to-UI Intermediate Representation (IR) Protocol & Conversion Engine
<strong>English</strong> |
简体中文
What UIX Is (and What It Is Not)
UIX is a protocol layer and conversion engine, not a Chat UI framework.
If you need a full-featured React chat interface, use assistant-ui — it's excellent and battle-tested. UIX solves a different problem: normalizing AI output from any source into a single, stable format.
┌─────────────────────────┐
Vercel AI SDK ──────→ │ │
AgentX ─────────────→ │ UIX IR │ ──→ assistant-ui
AG-UI (CopilotKit) ─→ │ (unified format) │ ──→ your own renderer
A2UI (Google) ──────→ │ │ ──→ any UI framework
└─────────────────────────┘
Think of UIX as Babel for AI output — Babel normalizes JavaScript across engines; UIX normalizes AI output across providers.
The Problem
AI backends all speak different formats:
| Source | Message Format | Tool Call Format | Streaming Protocol |
|---|---|---|---|
| Vercel AI SDK | UIMessage.parts[] | ToolInvocationPart | Data Stream |
| AgentX | Conversation.blocks[] | ToolBlock | WebSocket events |
| AG-UI (CopilotKit) | AG-UI events | ToolCallStart/End | SSE events |
| A2UI (Google) | Declarative UI payload | Component-based | gRPC stream |
If you build a chat UI, you're locked into one format. Switch backends? Rewrite your UI layer.
UIX IR eliminates this coupling. Your UI only knows LucidConversation and LucidBlock — adapters handle the rest.
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ AI Backends (upstream) │
│ Vercel AI SDK · AgentX · AG-UI · A2UI · LangChain · ... │
└──────────────────────────┬──────────────────────────────────────┘
│
UIX Adapters (ACL)
Pure functions, zero side effects
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ UIX IR (@uix-ai/core) │
│ LucidConversation → LucidBlock[] │
│ 7 block types: text · tool · thinking · image · file · error · │
│ source │
│ JSON Schema + TypeScript types + type guards │
└──────────────────────────┬──────────────────────────────────────┘
│
┌───────────┴───────────┐
▼ ▼
┌──────────────────────┐ ┌──────────────────────────────────────┐
│ assistant-ui │ │ UIX Reference Renderer │
│ (recommended) │ │ @uix-ai/stream (StreamMarkdown) │
│ Full chat UI runtime│ │ @uix-ai/agent (ChatBubble, etc.) │
│ via ExternalStore │ │ Lightweight, zero-runtime │
└──────────────────────┘ └──────────────────────────────────────┘
Why Adapters Instead of Direct Integration?
In DDD terms, each AI backend is a separate Bounded Context. UIX adapters are the Anti-Corruption Layer (ACL) — the downstream consumer (UI) protects itself from upstream format changes.
- Upstream (AgentX, Vercel, etc.) owns its own types — no pressure to change
- Downstream (UI) only depends on UIX IR — immune to backend switches
- Adapters are pure functions:
fromX(input) → LucidConversation[]
UIX IR Specification
Core Types
interface LucidConversation {
id: string
role: 'user' | 'assistant' | 'system'
status: 'streaming' | 'completed' | 'error'
blocks: LucidBlock[]
timestamp: number
}
interface LucidBlock<T extends BlockType> {
id: string
type: T // 'text' | 'tool' | 'thinking' | 'image' | 'file' | 'error' | 'source'
status: 'streaming' | 'completed' | 'error'
content: ContentByType<T> // conditional type, inferred from T
}
Block Types
| Type | Description | Content |
|---|---|---|
text | Text content (supports streaming) | { text: string } |
tool | Tool/function call | { name, input, output, status } — 9-state lifecycle |
thinking | AI reasoning process | { reasoning: string } |
image | Image content | { url, alt, width, height } |
file | File attachment | { name, type, url, size } |
error | Error message | { code, message, details } |
source | Source citation | { sourceId, title, url, excerpt } |
Tool Lifecycle (9 states)
pending → streaming → ready → running → success
↓
approval-required → approved → success
→ denied
↓
error
Packages
Core (the value)
| Package | Description | Status |
|---|---|---|
@uix-ai/core | UIX IR types, JSON Schema, type guards | ✅ v0.0.2 |
Adapters (the bridge)
| Package | Converts From | Status |
|---|---|---|
@uix-ai/adapter-vercel | Vercel AI SDK 4.x / 6.x | ✅ v0.0.2 |
@uix-ai/adapter-agui | AG-UI protocol (CopilotKit) | 🚧 Alpha |
@uix-ai/adapter-a2ui | A2UI protocol (Google) | 🧪 Experimental |
@uix-ai/adapter-agentx | AgentX Presentation | 🔜 Planned |
Reference Renderers (optional)
These are not the core value of UIX. They are lightweight reference implementations. For production chat UI, we recommend assistant-ui.
| Package | Description | Status |
|---|---|---|
@uix-ai/stream | Streaming Markdown renderer (Streamdown + Shiki |