Files
wehub-resource-sync e30e75b5d4
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
Changesets / Create Version PR (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00

4.1 KiB

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:

  1. Add persistence: Save messages to localStorage or a database
  2. Implement streaming: Update messages as they stream in
  3. Add branching: Allow users to explore different conversation paths
  4. Enable editing: Let users edit messages
  5. Add attachments: Support file uploads and images
  6. Connect to AI: Integrate with OpenAI, Anthropic, or other AI providers

Learn More