Files
Khalid Abdi 929bec8f31 feat: AI-added records save with placeholders + "Added by AI" provenance
Stop blocking AI imports/proposals on missing non-critical fields. Records
the chat agent drafts now save with safe placeholders, auto-generated file
numbers, and a source="ai" marker that surfaces an "Added by AI" badge so a
clinician can review/edit them later.

Backend:
- add `source` (manual|ai) column to patients/appointments/prescriptions
  (migration 0014) + canonical types, services, validation schemas
- relax patient/appointment validation: empty file number allowed, demographic
  + type/provider/initials fall back to placeholders (initials derived from name)
- patients.generateFileNumber() auto-assigns an MRN when one is missing
- proposeAppointment accepts a name when no file number resolves; AI commits +
  /api/ai/import stamp source="ai"

Frontend:
- `source` on Appointment/Patient/Prescription types; AI commits send source="ai"
- reusable <AiBadge> shown on the Patients table/detail and prescriptions list

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 19:27:17 +03:00

5.5 KiB

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.

See scripts/checkpoint.tsx for this example.

Installation

npx ai-elements@latest add checkpoint

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:

"use client";

import { useState, Fragment } from "react";
import { useChat } from "@ai-sdk/react";
import {
  Checkpoint,
  CheckpointIcon,
  CheckpointTrigger,
} from "@/components/ai-elements/checkpoint";
import {
  Message,
  MessageContent,
  MessageResponse,
} from "@/components/ai-elements/message";
import {
  Conversation,
  ConversationContent,
} from "@/components/ai-elements/conversation";

type CheckpointType = {
  id: string;
  messageIndex: number;
  timestamp: Date;
  messageCount: number;
};

const CheckpointDemo = () => {
  const { messages, setMessages } = useChat();
  const [checkpoints, setCheckpoints] = useState<CheckpointType[]>([]);

  const createCheckpoint = (messageIndex: number) => {
    const checkpoint: CheckpointType = {
      id: nanoid(),
      messageIndex,
      timestamp: new Date(),
      messageCount: messageIndex + 1,
    };
    setCheckpoints([...checkpoints, checkpoint]);
  };

  const restoreToCheckpoint = (messageIndex: number) => {
    // Restore messages to checkpoint state
    setMessages(messages.slice(0, messageIndex + 1));
    // Remove checkpoints after this point
    setCheckpoints(checkpoints.filter((cp) => cp.messageIndex <= messageIndex));
  };

  return (
    <div className="max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]">
      <Conversation>
        <ConversationContent>
          {messages.map((message, index) => {
            const checkpoint = checkpoints.find(
              (cp) => cp.messageIndex === index
            );

            return (
              <Fragment key={message.id}>
                <Message from={message.role}>
                  <MessageContent>
                    <MessageResponse>{message.content}</MessageResponse>
                  </MessageContent>
                </Message>
                {checkpoint && (
                  <Checkpoint>
                    <CheckpointIcon />
                    <CheckpointTrigger
                      onClick={() =>
                        restoreToCheckpoint(checkpoint.messageIndex)
                      }
                    >
                      Restore checkpoint
                    </CheckpointTrigger>
                  </Checkpoint>
                )}
              </Fragment>
            );
          })}
        </ConversationContent>
      </Conversation>
    </div>
  );
};

export default CheckpointDemo;

Use Cases

Manual Checkpoints

Allow users to manually create checkpoints at important conversation points:

<Button onClick={() => createCheckpoint(messages.length - 1)}>
  Create Checkpoint
</Button>

Automatic Checkpoints

Create checkpoints automatically after significant conversation milestones:

useEffect(() => {
  // Create checkpoint every 5 messages
  if (messages.length > 0 && messages.length % 5 === 0) {
    createCheckpoint(messages.length - 1);
  }
}, [messages.length]);

Branching Conversations

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

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

  // Restore to checkpoint
  restoreToCheckpoint(messageIndex);
};

Props

<Checkpoint />

Prop Type Default Description
children React.ReactNode - The checkpoint icon and trigger components. Automatically includes a Separator at the end.
...props React.HTMLAttributes<HTMLDivElement> - Any other props are spread to the root div.

<CheckpointIcon />

Prop Type Default Description
children React.ReactNode - Custom icon content. If not provided, defaults to a BookmarkIcon from lucide-react.
...props LucideProps - Any other props are spread to the BookmarkIcon component.

<CheckpointTrigger />

Prop Type Default Description
children React.ReactNode - The text or content to display in the trigger button.
tooltip string - Optional tooltip text shown on hover.
variant string - The button variant style.
size string - The button size.
...props React.ComponentProps<typeof Button> - Any other props are spread to the underlying shadcn/ui Button component.