Checkpoint

A simple component for marking conversation history points and restoring the chat to a previous state.

The Checkpoint component provides a way to mark specific points in a conversation history and restore the chat to that state. Inspired by VSCode's Copilot checkpoint feature, it allows users to revert to an earlier conversation state while maintaining a clear visual separation between different conversation segments.

Install using CLI

AI Elements Vue
shadcn-vue CLI
npx ai-elements-vue@latest add checkpoint

Install Manually

Copy and paste the following code in the same folder.

Checkpoint.vue
CheckpointIcon.vue
CheckpointTrigger.vue
index.ts
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { Separator } from '@repo/shadcn-vue/components/ui/separator'
import { cn } from '@repo/shadcn-vue/lib/utils'

const props = defineProps<{
  class?: HTMLAttributes['class']
}>()
</script>

<template>
  <div
    :class="cn('flex items-center gap-0.5 text-muted-foreground', props.class)"
    v-bind="$attrs"
  >
    <slot />
    <Separator />
  </div>
</template>

Features

  • Simple flex layout with icon, trigger, and separator
  • Visual separator line for clear conversation breaks
  • Clickable restore button for reverting to checkpoint
  • Customizable icon (defaults to BookmarkIcon)
  • Keyboard accessible with proper ARIA labels
  • Responsive design that adapts to different screen sizes
  • Seamless light/dark theme integration

Usage with AI SDK

Build a chat interface with conversation checkpoints that allow users to restore to previous states.

Add the following component to your frontend:

pages/index.vue
<script setup lang="ts">
import { useChat } from '@ai-sdk/vue'
import { nanoid } from 'nanoid'
import { computed, ref } from 'vue'
import {
  Checkpoint,
  CheckpointIcon,
  CheckpointTrigger,
} from '@/components/ai-elements/checkpoint'
import {
  Conversation,
  ConversationContent,
} from '@/components/ai-elements/conversation'
import {
  Message,
  MessageContent,
  MessageResponse,
} from '@/components/ai-elements/message'

interface CheckpointType {
  id: string
  messageIndex: number
  timestamp: Date
  messageCount: number
}

const { messages, setMessages } = useChat()
const checkpoints = ref<CheckpointType[]>([])

const messagesWithCheckpoints = computed(() => {
  return messages.value.map((message, index) => {
    const checkpoint = checkpoints.value.find(
      cp => cp.messageIndex === index
    )
    return { message, index, checkpoint }
  })
})

function createCheckpoint(messageIndex: number) {
  const checkpoint: CheckpointType = {
    id: nanoid(),
    messageIndex,
    timestamp: new Date(),
    messageCount: messageIndex + 1,
  }
  checkpoints.value.push(checkpoint)
}

function restoreToCheckpoint(messageIndex: number) {
  // Restore messages to checkpoint state (assuming setMessages API is the same)
  setMessages(messages.value.slice(0, messageIndex + 1))
  // Remove checkpoints after this point
  checkpoints.value = checkpoints.value.filter(
    cp => cp.messageIndex <= messageIndex
  )
}
</script>

<template>
  <div
    class="max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]"
  >
    <Conversation>
      <ConversationContent>
        <template
          v-for="{ message, checkpoint } in messagesWithCheckpoints"
          :key="message.id"
        >
          <Message :from="message.role">
            <MessageContent>
              <MessageResponse>{{ message.content }}</MessageResponse>
            </MessageContent>
          </Message>

          <Checkpoint v-if="checkpoint">
            <CheckpointIcon />
            <CheckpointTrigger
              @click="restoreToCheckpoint(checkpoint.messageIndex)"
            >
              Restore checkpoint
            </CheckpointTrigger>
          </Checkpoint>
        </template>
      </ConversationContent>
    </Conversation>
  </div>
</template>

Use Cases

Manual Checkpoints

Allow users to manually create checkpoints at important conversation points:

<Button @click="createCheckpoint(messages.length - 1)">
  Create Checkpoint
</Button>

Automatic Checkpoints

Create checkpoints automatically after significant conversation milestones:

watch(
  () => messages.value.length,
  (length) => {
    // Create checkpoint every 5 messages
    if (length > 0 && length % 5 === 0) {
      createCheckpoint(length - 1)
    }
  }
)

Branching Conversations

Use checkpoints to enable conversation branching where users can explore different conversation paths:

function restoreAndBranch(messageIndex: number) {
  // Save current branch
  const currentBranch = messages.value.slice(messageIndex + 1)
  saveBranch(currentBranch)

  // Restore to checkpoint
  restoreToCheckpoint(messageIndex)
}

Props

<Checkpoint />

classstring
''
The class name to apply to the component.

<CheckpointIcon />

classstring
''
The class name to apply to the component.

<CheckpointTrigger />

tooltipstring
''
The tooltip text to display when the trigger is hovered.
variantstring
'ghost'
The variant of the button (e.g., 'ghost', 'outline', 'solid').
sizestring
'sm'
The size of the button (e.g., 'sm', 'md', 'lg').