e30e75b5d4
Changesets / Create Version PR (push) Waiting to run
Code Quality / Oxlint + Oxfmt (push) Waiting to run
Code Quality / Template Sync (push) Waiting to run
Code Quality / Build Changed Packages (push) Waiting to run
Code Quality / Test Changed Packages (push) Waiting to run
Deploy Expo Example / Deploy Production (push) Waiting to run
Deploy Ink Example / Deploy Production (push) Waiting to run
Python Tests / pytest (assistant-stream, 3.10) (push) Waiting to run
Python Tests / pytest (assistant-stream, 3.12) (push) Waiting to run
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Waiting to run
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Waiting to run
Deploy Shadcn Registry / Deploy Production (push) Waiting to run
Template Metrics / LOC + Bundle Size (push) Waiting to run
Tap-Native Runtime Example
This example demonstrates the first tap-native runtime implementation for assistant-ui using @assistant-ui/tap and @assistant-ui/store.
Features
- ✅ ExternalThread: Display messages from external state
- ✅ InMemoryThreadList: Simple thread list management
- ✅ Reactive Updates: State changes automatically update the UI
- ✅ Type-Safe: Full TypeScript support with client registry
- ✅ No Backend: Pure client-side implementation
Getting Started
# From the monorepo root, install dependencies
pnpm install
# Navigate to this example
cd examples/with-tap-runtime
# Run the development server
pnpm dev
Open http://localhost:3000 to see the example.
How It Works
1. Define Messages
const messages: ExternalThreadMessage[] = [
{
id: "1",
role: "user",
content: [{ type: "text", text: "Hello!" }],
},
{
id: "2",
role: "assistant",
content: [{ type: "text", text: "Hi there!" }],
},
];
2. Create Runtime
const aui = useAui({
threads: InMemoryThreadList({
thread: () => ExternalThread({ messages, isRunning: false }),
}),
});
3. Provide to App
<AuiProvider value={aui}>
<Thread.Root>
<Thread.Messages />
</Thread.Root>
</AuiProvider>
Architecture
┌─────────────────────────────────────┐
│ React State (messages, isRunning) │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ useAui (tap-native runtime) │
│ ┌───────────────────────────────┐ │
│ │ InMemoryThreadList │ │
│ │ └─ ExternalThread │ │
│ │ └─ MessageClient │ │
│ │ └─ ComposerClient │ │
│ └───────────────────────────────┘ │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Assistant UI Components │
│ <Thread.Messages /> │
└─────────────────────────────────────┘
Key Concepts
ExternalThread
A client that accepts messages from external state:
ExternalThread({
messages: ExternalThreadMessage[],
isRunning?: boolean
})
InMemoryThreadList
A client that manages thread list state:
InMemoryThreadList({
thread: () => ResourceElement<ClientOutput<"thread">>
})
Client Registry
Type-safe client definitions via module augmentation (defined in @assistant-ui/react):
declare module "@assistant-ui/store" {
interface ScopeRegistry {
threads: ThreadsClientSchema;
thread: ThreadClientSchema;
message: MessageClientSchema;
// ...
}
}
Extending This Example
You can extend this example to:
- Add persistence: Save messages to localStorage or a database
- Implement streaming: Update messages as they stream in
- Add branching: Allow users to explore different conversation paths
- Enable editing: Let users edit messages
- Add attachments: Support file uploads and images
- Connect to AI: Integrate with OpenAI, Anthropic, or other AI providers