← Toda la documentación

Autocompletado con texto fantasma en línea

Cuando el usuario deja de escribir, el editor solicita a una función que tú proporcionas una continuación de la oración y la muestra en gris después del cursor. Tab la acepta; cualquier otra acción la descarta. El editor no incluye ningún modelo de IA ni realiza llamadas de red por su cuenta: tu función decide de dónde procede el texto.

El editor con la oración Our support team answers, seguida de una sugerencia gris: every ticket within one business day.
El texto gris es la sugerencia. No forma parte del documento hasta que el usuario pulsa Tab.

Cómo activarlo

Esta función la ofrece el plugin ghostcomplete.js (también incluido en plugins/all_plugins.js). No tiene botón en la barra de herramientas. Solo se ejecuta cuando ghostText está configurado y ghostTextResolver es una función.

<link rel="stylesheet" href="/richtexteditor/rte_theme_default.css">
<script src="/richtexteditor/rte.js"></script>
<script src="/richtexteditor/plugins/ghostcomplete.js"></script>

<div id="editor"><p>Our support team answers</p></div>
<script>
var editor = new RichTextEditor("#editor", {
    ghostText: true,
    ghostTextResolver: function (ctx) {
        return fetch("/api/complete", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ before: ctx.before })
        })
            .then(function (r) { return r.json(); })
            .then(function (data) { return data.text; });
    }
});
</script>

Aquí /api/complete es tu propio endpoint. Recibe el texto anterior al cursor, consulta el modelo que uses (conserva la clave de API en el servidor) y responde { "text": " every ticket within one business day." }. Inicia el texto devuelto con un espacio cuando continúe después de una palabra, porque se inserta exactamente como se devuelve.

Qué recibe y devuelve el resolver

ghostTextResolver(ctx) se llama con:

  • ctx.before: el texto desde el principio del párrafo actual (o encabezado, elemento de lista, celda…) hasta el cursor, limitado a los últimos maxContext caracteres;
  • ctx.after: el texto desde el cursor hasta el final de ese bloque;
  • ctx.full: el texto de todo el documento.

Devuelve una cadena o una Promise de una cadena. Una cadena vacía, un valor que no sea una cadena, un error lanzado o una Promise rechazada no muestran nada. Si el usuario vuelve a escribir antes de que llegue la respuesta, esta se descarta. Solo se solicita una sugerencia cuando ctx.before tiene al menos minChars caracteres que no sean espacios y no hay nada seleccionado.

Opciones

OpciónValor predeterminadoFunción
ghostTextfalsetrue, o un objeto con los tres ajustes siguientes, activa la función.
ghostText.delayMs600Pausa después de la última entrada antes de llamar al resolver. Usa un número positivo: 0 se considera sin definir y da 600.
ghostText.minChars3Número mínimo de caracteres que no sean espacios antes del cursor.
ghostText.maxContext2000Número máximo de caracteres que se pasan en ctx.before.
ghostTextResolvernullTu función, tal como se describe arriba.

Teclas y API

  • Tab acepta la sugerencia. Se inserta como texto escrito, de modo que un solo Ctrl+Z la elimina.
  • Escape, las flechas, Home, End, PageUp y PageDown la descartan. Escribir cualquier carácter la descarta e inicia una nueva espera.
  • Hacer clic o tocar el texto gris lo acepta (la única forma en un teléfono, que no tiene tecla Tab). Hacer clic en cualquier otro sitio lo descarta.

Métodos: editor.setGhostTextResolver(fn) sustituye el resolver durante la ejecución; editor.requestGhostText() solicita una sugerencia de inmediato, sin esperar; editor.acceptGhostText(), editor.dismissGhostText() y editor.hasGhostText() hacen lo que indican sus nombres. Con el plugin de comandos con barra cargado, el menú "/" tiene una entrada "AI complete" que llama a requestGhostText(). Si no hay un resolver configurado, esa llamada muestra una breve nota en el editor que indica que el autocompletado no está configurado.

Aspectos a tener en cuenta

  • Mientras se muestra, la sugerencia es este elemento después del cursor:
    <span class="rte-ghost" contenteditable="false" data-rte-ghost="1" aria-hidden="true"> every ticket within one business day.</span>
    getHTMLCode(), getHTMLContent() y getJSON() lo eliminan, de modo que el HTML guardado solo contiene texto aceptado por el usuario. Los lectores de pantalla lo omiten (aria-hidden).
  • El recuento de palabras y caracteres de la barra inferior incluye el texto gris mientras se muestra.
  • Cada pausa al escribir produce una llamada a tu endpoint. Limita la frecuencia y usa caché en el servidor, y aumenta delayMs si las llamadas tienen costo.
  • requestGhostText() también necesita que ghostText esté configurado; con solo un resolver no hace nada.

Relacionado: AI Toolkit (acciones de IA mediante comandos), proveedores de IA y streaming, demo de asistencia de escritura.