Copilot

Loading...
Files
components/copilot-demo.tsx
'use client';

import React from 'react';

import { Plate } from '@udecode/plate-common/react';

import { editorPlugins } from '@/components/editor/plugins/editor-plugins';
import { useCreateEditor } from '@/components/editor/use-create-editor';
import { copilotValue } from '@/components/values/copilot-value';
import { Editor, EditorContainer } from '@/components/plate-ui/editor';

import { copilotPlugins } from '../components/editor/plugins/copilot-plugins';

export default function CopilotDemo() {
  const editor = useCreateEditor({
    plugins: [...copilotPlugins, ...editorPlugins],
    value: copilotValue,
  });

  return (
    <Plate editor={editor}>
      <EditorContainer variant="demo">
        <Editor />
      </EditorContainer>
    </Plate>
  );
}

Features

  • Renders ghost text suggestions as you type
  • Two trigger modes:
    • Shortcut (Ctrl+Space). Press again for alternative suggestions.
    • Debounce mode: automatically triggers after a space at paragraph ends
  • Accept suggestions with Tab or word-by-word with Cmd+→
  • Built-in support for Vercel AI SDK completion API

Installation

npm install @udecode/plate-ai @udecode/plate-markdown

Usage

import { CopilotPlugin } from '@udecode/plate-ai/react';
import {
  MarkdownPlugin,
  serializeMdNodes,
  stripMarkdown,
} from '@udecode/plate-markdown';
const plugins = [
  // ...otherPlugins,
  MarkdownPlugin.configure({ options: { indentList: true } }),
  CopilotPlugin.configure(({ api }) => ({
    options: {
    completeOptions: {
      api: '/api/your-api-endpoint',
      body: {
        system: `You are an advanced AI writing assistant, similar to VSCode Copilot but for general text. Your task is to predict and generate the next part of the text based on the given context.
 
Rules:
- Continue the text naturally up to the next punctuation mark (., ,, ;, :, ?, or !).
- Maintain style and tone. Don't repeat given text.
- For unclear context, provide the most likely continuation.
- Handle code snippets, lists, or structured text if needed.
- Don't include """ in your response.
- CRITICAL: Always end with a punctuation mark.
- CRITICAL: Avoid starting a new block. Do not use block formatting like >, #, 1., 2., -, etc. The suggestion should continue in the same block as the context.
- If no context is provided or you can't generate a continuation, return "0" without explanation.`,
      },
      onFinish: (_, completion) => {
        if (completion === '0') return;
 
        api.copilot.setBlockSuggestion({
          //stripMarkdownBlocks in plus GhostText
          text: stripMarkdown(completion),
        });
      },
    },
    debounceDelay: 500,
    getPrompt: ({ editor }) => {
      const contextEntry = getAncestorNode(editor);
 
      if (!contextEntry) return '';
 
      const prompt = serializeMdNodes([contextEntry[0] as TElement]);
 
      return `Continue the text up to the next punctuation mark:
"""
${prompt}
"""`;
    },
    renderGhostText: GhostText,
  },
}));

Tab Key Handling

The Copilot plugin uses the Tab key to accept suggestions. To avoid conflicts with other plugins that use Tab (like IndentPlugin or TabbablePlugin), ensure CopilotPlugin is placed before them in your plugin configuration. This allows Copilot to handle Tab key events first when suggestions are present.

const plugins = [
  // ...otherPlugins,
  CopilotPlugin,
  // Place tab-using plugins after Copilot
  IndentPlugin,
  TabbablePlugin,
];

Examples

Plate UI

Refer to the preview above.

Plate Plus

Keyboard Shortcuts

KeyDescription
Ctrl + Space

Trigger suggestion. Press again for alternative suggestions.

TabAccept the entire suggestion.
Cmd + →

Accept the next word of the suggestion.

EscapeDismiss the current suggestion.

Plugins

CopilotPlugin

Options

Collapse all

    Additional conditions to auto trigger copilot. Default checks:

    • Block above is not empty
    • Block above ends with a space
    • No existing suggestion

    AI completion configuration options. See AI SDK useCompletion Parameters.

    Delay for debouncing auto-triggered suggestions. Default: 0

    Function to extract the next word from suggestion text.

    Function to generate the prompt for AI completion. Default: Uses markdown serialization of ancestor node

    Component to render ghost text suggestions.

    Conditions to trigger copilot. Default checks:

    • Selection is not expanded
    • Selection is at block end

API

editor.api.copilot.accept()

Accepts the current suggestion.

editor.api.copilot.acceptNextWord()

Accepts the next word of the suggestion.

editor.api.copilot.reset()

Resets the plugin state:

  • Aborts any ongoing API request
  • Clears the current completion
  • Clears suggestion node ID and text

editor.api.copilot.setBlockSuggestion()

Sets suggestion text for a block.

Parameters

Collapse all

editor.api.copilot.stop()

Stops ongoing suggestion requests:

  • Cancels debounced trigger calls
  • Aborts current API request
  • Resets abort controller

editor.api.copilot.triggerSuggestion()

Triggers a new suggestion request. Can be debounced based on plugin configuration.