Text Editor - AI Improve Plugin

Improve selected text using Claude AI with real-time streaming.

#Usage

import { TextEditor } from '@primeui/vue-texteditor';
import { aiImprovePlugin } from './ai-improve-plugin';
<TextEditor.Root v-model="value" :plugins="[aiImprovePlugin]">
    <TextEditor.ContextToolbar>
        <AIButton />
    </TextEditor.ContextToolbar>
    <TextEditor.Content />
</TextEditor.Root>

The AI Improve plugin adds an improve command that rewrites the selected text for grammar, spelling, and clarity, streaming the result back into the selection. Pass aiImprovePlugin through the plugins prop, then call pluginCommands.aiImprove?.improve() from a toolbar widget. The plugin owns the model request and streaming; the editor owns the selection it replaces.

#Overview

The plugin rewrites the selected text through the Anthropic Claude API. The response streams token-by-token over Server-Sent Events, so the selection is replaced incrementally as the model generates output.

#Plugin Definition

import { defineTextEditorPlugin } from '@primeui/vue-texteditor';

export interface AIImproveOptions {
    model?: string;
}

export const aiImprovePlugin = defineTextEditorPlugin<AIImproveOptions>('aiImprove', ({ getSelectedText, replaceSelection, options }) => {
    const model = options?.model ?? 'claude-haiku-4-5-20251001';

    return {
        commands: {
            improve: async () => {
                const text = getSelectedText();

                if (!text) return;

                const response = await fetch('/api/ai-improve', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ text, model })
                });

                if (!response.ok || !response.body) return;

                // Clear the selection; the cursor is now at the insertion point
                replaceSelection('');

                // Parse SSE stream and insert chunks as they arrive
                const reader = response.body.getReader();
                const decoder = new TextDecoder();
                let buffer = '';

                while (true) {
                    const { done, value } = await reader.read();

                    if (done) break;

                    buffer += decoder.decode(value, { stream: true });
                    const lines = buffer.split('\n');

                    buffer = lines.pop() ?? '';

                    for (const line of lines) {
                        if (!line.startsWith('data: ')) continue;

                        const data = line.slice(6);

                        if (data === '[DONE]') break;

                        try {
                            const event = JSON.parse(data);

                            if (event.type === 'content_block_delta' && event.delta?.text) {
                                replaceSelection(event.delta.text);
                            }
                        } catch {
                            // skip non-JSON lines
                        }
                    }
                }
            }
        }
    };
});

#Options

OptionTypeDefaultDescription
modelstring'claude-haiku-4-5-20251001'Claude model to use

#Commands

CommandSignatureDescription
improve() => Promise<void>Improves selected text using Claude AI with streaming

#Example

Select text in the editor to open the ContextToolbar, then click the AI button.

Live demo, rate limited. The button may be inactive once the limit is hit.
Loading Demo...