Erweiterungsmöglichkeiten für Annotationen
Mit der Browser Annotation API kann Ihre Website anpassen, was Personen auswählen, welcher Kontext ihrem Feedback beigefügt wird und welche Steuerelemente sie zur Vorschau von Änderungen verwenden, bevor sie eine Annotation an ChatGPT senden.
Browserannotationen funktionieren auf Ihrer Website ohne Codeänderungen. Personen können einen Teil einer Seite auswählen, einen Kommentar hinzufügen und ihn als Kontext an Codex oder ChatGPT Work senden.
Als Entwickler können Sie mit der Browser Annotation API Kontext oder Steuerelemente bereitstellen, die auf Ihre Anwendung zugeschnitten sind. Sie können beispielsweise in einer Designsystem-Vorschau Vorschauen für Komponentenvarianten hinzufügen, damit Entwickler wissen, wie sie die Komponenten auf einer Website aktualisieren können.
Wenn Sie Hilfe beim Verständnis der Browser Annotation API oder beim Hinzufügen der Annotationsunterstützung zu Ihrer Website benötigen, installieren Sie das Plugin Annotations Extensibility.
Das Plugin Annotations Extensibility installieren
Ausprobieren
Erleben Sie die Browser Annotation API in dieser Anleitung in Aktion.
- Öffnen Sie diese Seite im integrierten Browser von ChatGPT.
- Öffnen Sie testweise den vorgeschlagenen Prompt, der in dieser Karte erscheint.
- Wechseln Sie in den Annotationsmodus und wählen Sie dann die folgende Tabelle oder ein Codebeispiel aus, um zwischen vordefinierten Layouts und Designs zu wechseln.
- Sie können weiterhin jedes Element auf der Seite annotieren und das standardmäßige Annotationsverhalten ausprobieren.
Öffnen Sie diese Seite im integrierten Browser von ChatGPT, um Anmerkungen auszuprobieren.
Wählen Sie aus, was Sie anpassen möchten
Beginnen Sie mit der Integration, die zu Ihrer Website passt:
| Ziel | Integration |
|---|---|
| Eine Karte oder eine andere Elementgruppe als einzelnes Objekt auswählbar machen | Auswahlziele |
| Personen die Auswahl einer Wortgruppe oder eines Satzes ermöglichen | Textauswahlcontainer |
| Einer Auswahl zusätzlichen Kontext beifügen | Auswahlmetadaten |
| Eine Annotation über eine eigene Schaltfläche mit einem vorgeschlagenen Kommentar öffnen | Annotationsanfragen |
| Über die eigene Benutzeroberfläche Feedback zu einer bestimmten Textpassage anfordern | Textbereichsanfragen |
| Beim Öffnen einer Annotation erweiterte Steuerelemente anzeigen | Editor-Standardeinstellungen |
| Anwendungseigenschaften als Vorschau anzeigen oder Auswahlentscheidungen erfassen | Benutzerdefinierte Steuerelemente |
| Einzelne Objekte auswählen, die in einem Canvas gezeichnet sind | Annotationsflächen |
| Den Annotationsmodus über Ihre Website ein- oder ausschalten | Steuerung des Annotationsmodus |
Diese Anleitung bezieht sich auf die zur DevDay 2026 veröffentlichte Version der ChatGPT-Desktop-App und spätere Versionen.
Die JavaScript-API ist über document.oai.annotation im integrierten Browser der App
auf sicheren Seiten der obersten Ebene verfügbar, etwa über HTTPS oder localhost. Wenn sie
aktiviert ist, installiert der Browser sie, bevor die Skripte Ihrer Seite ausgeführt werden. Prüfen Sie die Verfügbarkeit
jeder Methode, um ältere oder nicht unterstützte Browser zu berücksichtigen, und initialisieren Sie Ihre
Integration, sobald deren DOM-Elemente vorhanden sind. Weder ein Bereitschaftsereignis noch Polling ist erforderlich.
API-Methoden kehren synchron zurück, und Registrierungs-Handles können
sofort verwendet werden. Der Browser kann den Annotationseditor anschließend fertig laden.
Der hitTest-Callback einer Fläche kann ein Promise zurückgeben.
Auswahlziele anpassen
Standardmäßig wählt der Annotationsmodus Elemente aus dem DOM der Seite aus und bevorzugt dabei
Ziele wie Text, Bilder und Steuerelemente. Um ein größeres Objekt auswählbar zu machen,
kennzeichnen Sie seinen umschließenden Bereich mit oai-annotation-container und seine auswählbaren
Nachfahren mit oai-annotatable.
Dieses Beispiel macht eine Diagrammkarte als einzelnes Objekt auswählbar:
<section oai-annotation-container>
<article id="chart-card" oai-annotatable="Q3 Revenue">
<h2>Q3 Revenue</h2>
<p>$120,000 this quarter</p>
<button type="button">More info</button>
</article>
</section>Wenn Sie auf eine beliebige Stelle innerhalb der Karte zeigen, wird die gesamte Karte hervorgehoben. Der optionale
Wert oai-annotatable gibt dem Objekt einen Namen, der dem Benutzer und dem Modell angezeigt wird.
Wählen Sie Namen, die benachbarte Objekte voneinander unterscheiden, oder lassen Sie den Wert weg.
Der Container legt fest, wo diese Auswahlregeln gelten. Ein
oai-annotatable-Attribut allein ändert das Auswahlverhalten nicht.
Innerhalb eines Containers wählt der Browser das nächstgelegene markierte Ziel aus, das
das Element unter dem Zeiger enthält. Bei verschachtelten Containern wird der nächstgelegene Container verwendet.
Nicht markierte Bereiche innerhalb eines Containers erzeugen eine Webseitenannotation; Bereiche außerhalb
aller Container behalten das Standardverhalten bei.
Textauswahl aktivieren
Fügen Sie einem Bereich oai-annotation-container-text hinzu, damit Personen im Annotationsmodus Text
durch Ziehen auswählen können. Das Attribut benötigt keinen Wert:
<article oai-annotation-container-text>
<h2>Design guidelines</h2>
<p>Use consistent spacing between related components.</p>
<p>Leave more space between separate groups.</p>
</article>Beim Loslassen einer nicht leeren Auswahl wird der Textannotationseditor mit dem ausgewählten Bereich und dessen Kontext geöffnet. Ein Klick ohne Textauswahl erstellt keine Annotation. Escape oder eine abgebrochene Geste bricht die Auswahl ab.
Der nächstgelegene Text- oder DOM-Auswahlcontainer bestimmt, wie eine Geste beginnt.
Textcontainer verwenden keine oai-annotatable-Markierungen zur Elementauswahl. Verschachteln Sie
einen oai-annotation-container, um die Elementauswahl wiederherzustellen, oder einen Textcontainer, um
die Textauswahl wiederherzustellen. Wenn beide Attribute auf einem Element vorhanden sind, hat die Textauswahl
Vorrang.
Die Textauswahl folgt den normalen Auswahlregeln der Seite und kann über
den Ausgangscontainer hinausreichen. Ein Container begrenzt den Bereich nicht und ermöglicht keine Auswahl
innerhalb eines iframe. Textfelder bleiben auswählbar, normale Seitenklicks und
native Aktionen auf Steuerelementen bleiben im Annotationsmodus jedoch blockiert. Explizite
request()-Aufrufe behalten ihr bisheriges Verhalten bei.
Einer Auswahl Kontext hinzufügen
Fügen Sie einem markierten Ziel oai-annotation-metadata hinzu, um Kontext einzubeziehen, der möglicherweise nicht
auf der Seite sichtbar ist. Beispielsweise kann eine fiktive Kontaktzeile eine
E-Mail-Adresse für eine Anfrage zum Verfassen einer E-Mail enthalten:
<section oai-annotation-container>
<div
id="contact-row"
oai-annotatable="Alex Morgan"
oai-annotation-metadata='{"email":"alex@example.com"}'
>
<div>Alex Morgan</div>
<div>Project lead</div>
</div>
</section>Wenn eine der beiden Zeilen ausgewählt wird, wird die gesamte Kontaktzeile ausgewählt. Die Metadaten erscheinen mit der Annotation und werden ihr in der Unterhaltung beigefügt. Fügen Sie nur Kontext hinzu, den Sie sowohl mit dem Benutzer als auch mit dem Modell teilen möchten. Zum Senden einer E-Mail wäre weiterhin ein verbundenes E-Mail-Tool erforderlich.
Verwenden Sie ein kleines, flaches JSON-Objekt mit diesen Grenzen:
- Bis zu sechs Eigenschaften mit Zeichenfolgen, endlichen Zahlen, booleschen Werten oder
nullals Werten. - Schlüssel mit bis zu 64 Zeichen und Zeichenfolgenwerte mit bis zu 256 Zeichen.
- Bis zu 2.048 Byte für das serialisierte Objekt.
Schlüssel müssen mit einem ASCII-Buchstaben beginnen und dürfen nur ASCII-Buchstaben, Ziffern, Leerzeichen, Unterstriche oder Bindestriche enthalten. Verwenden Sie einzelne Leerzeichen zwischen Wörtern. Verschachtelte Objekte und Arrays werden nicht unterstützt. Der Browser ignoriert ungültige Metadaten.
Sie können Metadaten auch über request() oder das hitTest-Ergebnis einer Fläche
bereitstellen.
Eine Annotation über Ihre Website öffnen
Rufen Sie document.oai.annotation.request(target, options) direkt aus einer Benutzerinteraktion
auf, beispielsweise dem Betätigen einer Schaltfläche. Das Ziel kann ein mit dem DOM verbundenes HTML-Element
im sichtbaren Bereich des aktuellen Dokuments oder ein
DOM-Range sein. Es benötigt keine Annotationsattribute.
Virtuelle Objekt-IDs werden nicht unterstützt.
Von der Website initiierte Anfragen können die Zustimmung des Benutzers erfordern; Benutzer können blockierte Annotationsfunktionen unter Site tools > Annotation features wieder aktivieren.
Fügen Sie diese Schaltfläche neben der Diagrammkarte aus dem Auswahlbeispiel hinzu und führen Sie das Skript aus, nachdem beide Elemente vorhanden sind:
<button id="discuss-chart" type="button" hidden>Explain more</button>const card = document.getElementById("chart-card");
const button = document.getElementById("discuss-chart");
button.hidden = typeof document.oai?.annotation?.request !== "function";
button.addEventListener("click", () => {
const annotation = document.oai?.annotation;
if (typeof annotation?.request !== "function") return;
annotation.request(card, {
initialComment: "Explain the latest trend in this graph.",
});
});Die Auswahl von Explain more fordert den Browser auf, eine Annotation mit ausgewählter Karte und einem bearbeitbaren Kommentar zu öffnen. Die Person kann ihn bearbeiten, speichern und mit ihrer Nachricht senden. Das Öffnen einer Annotation sendet keine Nachricht an ChatGPT; nur der Benutzer kann sie absenden.
Führen Sie den Aufruf innerhalb der aktiven Benutzerinteraktion aus. Wenn Sie zuerst auf eine Netzwerkanfrage warten, kann der Bezug zu dieser Interaktion verloren gehen.
Das optionale zweite Argument unterstützt diese Felder:
| Option | Verhalten |
|---|---|
mode |
Verwenden Sie "advanced", um erweiterte Steuerelemente für ein Element zu öffnen, oder "default" für das standardmäßige Editorverhalten. Der Standardwert ist "default". Benutzerdefinierte Steuerelemente können auch mit "default" geöffnet werden; siehe Editor-Standardeinstellungen. Textbereiche unterstützen nur "default". |
enterAnnotationMode |
Setzen Sie den Wert auf true, um in den Annotationsmodus zu wechseln und nach dem Abbrechen oder Senden der Annotation darin zu bleiben. |
metadata |
Gültige, nicht leere Metadaten ersetzen für diese Anfrage die HTML-Metadaten des Ziels. Diese Option wird bei Textbereichen und dann ignoriert, wenn sich das Zielelement innerhalb eines Shadow DOM befindet. |
initialComment |
Stellt einen bearbeitbaren Kommentar mit bis zu 240 UTF-16-Codeeinheiten bereit. |
request() gibt ein Objekt mit einem booleschen Wert accepted zurück. Prüfen Sie
result.accepted, nicht das Ergebnisobjekt, um festzustellen, ob der Browser die Anfrage empfangen
und validiert hat. Dies bestätigt weder, dass der Editor geöffnet wurde, noch, dass
die Person eine Annotation gespeichert oder gesendet hat.
Während der Editor geladen wird, kann der Browser eine akzeptierte Anfrage vorhalten. Er kann eine weitere ablehnen, während eine Anfrage aussteht, ein Editor geöffnet ist oder ChatGPT den Browser steuert.
Eine Annotation für einen Textbereich anfordern
Übergeben Sie einen DOM-Range, um Feedback zu einer Passage anzufordern, ohne die
Textauswahl des Browsers zu ändern. Dieses Beispiel wählt den Inhalt des Absatzes aus; es benötigt
kein oai-annotation-container-text-Attribut:
<p id="draft-passage">Leave more space between separate groups.</p>
<button id="discuss-passage" type="button" hidden>Discuss this passage</button>Führen Sie dieses Skript aus, nachdem beide Elemente vorhanden sind:
const passage = document.getElementById("draft-passage");
const button = document.getElementById("discuss-passage");
button.hidden = typeof document.oai?.annotation?.request !== "function";
button.addEventListener("click", () => {
const annotation = document.oai?.annotation;
if (typeof annotation?.request !== "function") return;
const range = document.createRange();
range.selectNodeContents(passage);
annotation.request(range, {
initialComment: "Suggest a clearer version of this guidance.",
});
});Der Bereich muss nicht leeren, sichtbaren Text im aktuellen Dokument enthalten, wobei sich mindestens ein Teil der Auswahl im sichtbaren Seitenbereich befinden muss. Er darf höchstens 20.000 UTF-16-Codeeinheiten enthalten. Auf einen Punkt reduzierte Textbereiche, Text ausschließlich aus Leerraum, ausgeblendeter ausgewählter Text und Bereiche in geschlossenen Shadow Roots werden nicht unterstützt.
Textbereichsanfragen verwenden ausschließlich den Standardtexteditor. Eine Anfrage mit
mode: "advanced" wird abgelehnt, und Anfragemetadaten werden ignoriert. Halten Sie den Zieltext
verfügbar, während eine akzeptierte Anfrage auf den Editor wartet: Der Browser
prüft den Bereich erneut, bevor er ihn öffnet. Textauswahlcontainer ermöglichen unabhängig davon,
dass Personen im Annotationsmodus Text durch Ziehen auswählen.
Den Standardmodus des Editors auswählen
Um erweiterte Steuerelemente bei Annotationen, die über die Auswahloberfläche des Browsers geöffnet werden,
sofort anzuzeigen, fügen Sie dieses Tag zum <head> Ihrer Seite hinzu:
<meta name="oai-annotation-editor-default-mode" content="advanced" />Für Annotationen, die über Ihre eigene Benutzeroberfläche geöffnet werden, übergeben Sie { mode: "advanced" } an
request(). Verwenden Sie mode: "default" oder lassen Sie es weg, um das standardmäßige Editorverhalten zu erhalten.
Die Metaeinstellung der Seite überschreibt diese Anfrageoption nicht. Der Standardmodus
garantiert keinen reinen Kommentareditor: Benutzerdefinierte Steuerelemente mit vorgeschlagenen Anfangswerten
oder Steuerelemente, bei denen currentValue weggelassen wird, können den Steuerelementeditor öffnen.
Manuelle Bedienelemente für Adjust, Einklappen und Wahltaste-Klick sind nur in Codex oder auf localhost verfügbar. Auf gehosteten Websites in ChatGPT erscheinen registrierte benutzerdefinierte Steuerelemente automatisch ohne Schaltfläche zum Adjust oder Einklappen. Der von der Seite angeforderte erweiterte Modus funktioniert dort weiterhin.
Benutzerdefinierte Steuerelemente hinzufügen
Verwenden Sie registerControls(), um Annotationssteuerelemente einem oder mehreren DOM-Elementen
zuzuordnen. Steuerelemente können Anwendungseigenschaften wie ein Abstandstoken als Vorschau anzeigen
oder Auswahlentscheidungen erfassen, die einer Anfrage beigefügt werden, etwa den Tonfall einer E-Mail.
Eine Vorschau für ein gemeinsam verwendetes Abstandstoken anzeigen
Beide Karten in diesem Beispiel verwenden dieselbe CSS-Eigenschaft:
<style>
#component-preview {
--card-padding: 16px;
}
.preview-card {
padding: var(--card-padding);
border: 1px solid #d1d5db;
}
</style>
<section id="component-preview" oai-annotation-container>
<article class="preview-card" oai-annotatable="Profile card">
Profile card
</article>
<article class="preview-card" oai-annotatable="Summary card">
Summary card
</article>
</section>Führen Sie dieses Skript aus, nachdem Sie die Vorschau erstellt haben:
const preview = document.getElementById("component-preview");
const annotation = document.oai?.annotation;
function previewSpacing(event) {
const { callback, value } = event.detail;
if (callback === "setCardPadding") {
preview.style.setProperty("--card-padding", `${value}px`);
}
}
let registration;
if (typeof annotation?.registerControls === "function") {
preview.addEventListener("oaiannotationcontrolchange", previewSpacing);
registration = annotation.registerControls({
targets: preview.querySelectorAll(".preview-card"),
controlsHeading: "Card spacing",
controlsMode: "replace",
controls: [
{
type: "range",
label: "Card padding (pixels)",
callback: "setCardPadding",
reference: "--card-padding",
min: 8,
max: 32,
step: 4,
currentValue: 16,
},
],
});
}
function disposeAnnotationControls() {
preview.style.removeProperty("--card-padding");
registration?.dispose();
preview.removeEventListener("oaiannotationcontrolchange", previewSpacing);
}Annotieren Sie eine der beiden Karten und ändern Sie Card padding (pixels) von 16 auf 24. Auf
gehosteten Websites in ChatGPT erscheinen die Steuerelemente automatisch; in Codex oder auf
localhost wählen Sie bei Bedarf Adjust. Beide Karten werden aktualisiert. Die Annotation erfasst die Beschriftung, die Referenz
sowie die alten und neuen Werte. Beim Löschen der Vorschau wird der ursprüngliche Innenabstand wiederhergestellt.
Rufen Sie disposeAnnotationControls() auf, wenn Sie die Komponente entfernen.
Eine Auswahl ohne Vorschau erfassen
Verwenden Sie die Kontaktzeile aus dem Metadatenbeispiel, um einen E-Mail-Tonfall zur Auswahl anzubieten:
const contact = document.getElementById("contact-row");
const registration = document.oai?.annotation?.registerControls?.({
targets: contact,
controlsHeading: "Email options",
controlsMode: "replace",
controls: [
{
type: "select",
label: "Email tone",
callback: "emailTone",
options: [
{ label: "Professional", value: "professional" },
{ label: "Friendly", value: "friendly" },
{ label: "Direct", value: "direct" },
],
defaultValue: "professional",
},
],
});Dieses Steuerelement benötigt keinen Ereignishandler, da es keine Vorschau einer Seitenänderung
anzeigt. Wenn Sie currentValue weglassen, weisen Sie den Browser an, den ausgewählten Tonfall einzubeziehen,
auch wenn der Benutzer die anfängliche Option beibehält. Rufen Sie registration?.dispose() auf, wenn Sie
die Zeile entfernen.
Bei Auswahlsteuerelementen erhalten Vorschau-Callbacks option.value, beispielsweise
"professional". Der Annotationsverlauf und ChatGPT erhalten die sichtbare
option.label, beispielsweise "Professional", sowohl für die vorherige als auch für die ausgewählte
Option. Verwenden Sie Beschriftungen, die jede Auswahlmöglichkeit erklären; interne IDs in value werden nicht
als Text der Auswahl gesendet.
Steuerelemente und Anfangswerte konfigurieren
Verwenden Sie controlsMode: "replace", um für die registrierten Ziele nur Ihre Steuerelemente
anzuzeigen, oder "extend", um sie zusammen mit integrierten Steuerelementen anzuzeigen. Eine optionale
controlsHeading benennt den Bereich. Der Browser entfernt umgebenden Leerraum und akzeptiert ein bis 80
Zeichen. Ohne Überschrift zeigt der Bereich das HTML-Tag des Elements an. Die
Überschrift wird nicht in den an ChatGPT gesendeten Kontext aufgenommen.
Eine Registrierung unterstützt bis zu 12 Steuerelemente. Jedes benötigt einen type, eine sichtbare
label und eine callback-Kennung:
| Typ | Wert | Zusätzliche Felder |
|---|---|---|
color |
Hexadezimale Farbe, etwa "#2563eb" |
Keine |
range |
Zahl | min, max und step |
select |
Zeichenfolge | options, ein Array aus { label, value }-Objekten |
toggle |
Boolescher Wert | Keine |
callback ist eine Zeichenfolgenkennung, keine JavaScript-Funktion. Gestalten Sie sie
innerhalb der Registrierung eindeutig, beginnen Sie mit einem ASCII-Buchstaben und verwenden Sie ASCII-Buchstaben,
Ziffern, Unterstriche oder Bindestriche. Eine optionale reference identifiziert die Eigenschaft,
die geändert wird, und wird der Beschriftung und dem Wert in der Annotation beigefügt.
Setzen Sie currentValue auf den gültigen regulären Wert der Eigenschaft, einschließlich nicht gespeicherter
Änderungen. Verwenden Sie weder den Vorschauzustand noch unvollständige Eingaben als Ausgangswert. Der Browser
verwendet ihn für Vorher-nachher-Änderungen und zum Zurücksetzen. Wenn sich der Anwendungszustand ändert, verwenden Sie
registration.update({ controls }), um die currentValue-Werte der Steuerelemente zu
aktualisieren. Aktualisierungen wirken sich auf künftige Annotationen aus; bestehende Annotationen behalten ihre
erfassten Werte.
Setzen Sie defaultValue für einen vorgeschlagenen Anfangswert; dieser hat Vorrang vor
currentValue für den anfänglichen Zustand
des Steuerelements. Wenn Sie beide weglassen, beginnt das Steuerelement bei einer Farbe mit Weiß, bei einem Wertebereich mit dem Minimum,
bei einer Auswahlliste mit der ersten Option oder bei einem Umschalter mit false.
Halten Sie vorgeschlagene Werte von regulären Entwürfen getrennt. Wenn eine Aktualisierung eine Ausnahme auslöst oder eine
Anfrage fehlschlägt oder accepted: false zurückgibt, verwerfen Sie den versuchten Vorschlag und
stellen Sie den vorherigen Zustand der Steuerelemente und Vorschläge wieder her. Behalten Sie Vorschläge bei, wenn eine Anfrage
akzeptiert wird: Der Browser kann sie in eine Warteschlange stellen, bevor er die Steuerelemente erfasst.
Steuerelemente und Registrierungen validieren
Der Browser validiert Registrierungen und Aktualisierungen anhand dieser Grenzen:
| Feld oder Ressource | Einschränkung |
|---|---|
| Steuerelemente | Bis zu 12 pro Registrierung mit eindeutigen callback-Kennungen. Verwenden Sie nur die für den Steuerelementtyp definierten Felder. |
| Beschriftungen und Überschriften | Steuerelementbeschriftungen, Optionsbeschriftungen und controlsHeading dürfen nach dem Entfernen umgebenden Leerraums nicht leer sein und höchstens 80 UTF-16-Codeeinheiten umfassen. Steuerelementtexte dürfen keine Steuerzeichen oder Zeichen enthalten, die die Schreibrichtung ändern. |
| Kennungen | callback umfasst nach dem Entfernen umgebenden Leerraums höchstens 80 UTF-16-Codeeinheiten und verwendet das oben beschriebene Format. reference umfasst 1–80 Zeichen und erlaubt ASCII-Buchstaben, Ziffern und _ . / : @ $ # -, ohne Leerzeichen. |
| Auswahloptionen | 1–12 Optionen mit unterschiedlichen value-Zeichenfolgen mit jeweils höchstens 512 UTF-16-Codeeinheiten. Angegebene Werte für currentValue und defaultValue müssen dem Wert einer Option entsprechen. |
| Wertebereichswerte | min, max, currentValue und defaultValue müssen endliche Zahlen zwischen −10.000 und 10.000 sein. Erforderlich sind min < max, ein step-Wert von 0,001 bis 10.000, der nicht größer als max - min ist, sowie Anfangswerte innerhalb des Bereichs. Anfangswerte müssen nicht an step ausgerichtet sein. |
| Farben und Umschalter | Farben müssen 3, 4, 6 oder 8 Hexadezimalziffern nach # verwenden. Werte für Umschalter müssen true oder false sein. |
| Ziele | 1–128 Zieleinträge bei der Registrierung, allesamt Elemente im aktuellen Dokument. Aktualisierungen können targets: [] übergeben, um die Zuordnung aufzuheben. Jedes Dokument unterstützt bis zu 64 Steuerelementregistrierungen und 1.024 Zuordnungen zwischen Registrierungen und Zielen. |
| Serialisierte Steuerelemente | Die JSON-Nutzlast mit controls, controlsHeading und controlsMode darf höchstens 16.384 UTF-16-Codeeinheiten umfassen. Verwenden Sie Daten, die als JSON codiert werden können, ohne Funktionen, Symbole oder große Ganzzahlen. |
registerControls() und registration.update() können bei ungültigen Definitionen,
Zielen oder überschrittenen Grenzen synchron Ausnahmen auslösen. Eine Aktualisierung nach dispose()
löst ebenfalls eine Ausnahme aus. Eine abgelehnte Aktualisierung erhält die vorherige Registrierung einschließlich
ihrer Steuerelemente und Ziele. Behandeln Sie Fehler an der Aufrufstelle, halten Sie die reguläre
Bearbeitung nutzbar und verwenden Sie eigene Registrierungen erneut oder geben Sie sie frei, um innerhalb der
Grenzen zu bleiben.
Vorschauen und Zurücksetzungen verarbeiten
Das oaiannotationcontrolchange-Ereignis wird vom ausgewählten Element aus im DOM nach oben weitergereicht. Sein
detail enthält callback, value und action:
| Aktion | Den bereitgestellten Wert anwenden, um |
|---|---|
preview |
die angeforderte Änderung anzuzeigen. |
preview-original |
vorübergehend den ursprünglichen Zustand zum Vergleich anzuzeigen. |
reset |
beim Löschen der Vorschau den ursprünglichen Zustand wiederherzustellen. |
Wenden Sie den bereitgestellten Wert bei jeder Aktion an, wie im Abstandsbeispiel. Gestalten Sie Handler reversibel und so, dass sie gefahrlos wiederholt aufgerufen werden können. Vorschauereignisse fordern keine dauerhafte Änderung an; speichern Sie über den normalen Speicherablauf Ihrer Anwendung. Halten Sie reguläre Entwürfe, unvollständige Eingaben und Vorschauen getrennt, damit unabhängige Änderungen keine Vorschau überschreiben. Wenn jemand dieselbe Einstellung bearbeitet, ersetzen Sie deren Vorschau und aktualisieren Sie den Ausgangswert für künftige Annotationen.
Bewahren Sie das Registrierungs-Handle für Aktualisierungen und die Bereinigung auf. update() akzeptiert jede
Kombination aus targets, controls, controlsHeading und controlsMode.
Weggelassene Felder behalten ihre bisherigen Werte. Verwenden Sie beispielsweise
registration.update({ targets: newElement }), wenn Sie das DOM-Element einer Komponente
ersetzen. Zielsammlungen erfassen vorhandene Elemente und verfolgen keine künftigen
Selektortreffer.
Übergeben Sie targets: [], um die Zuordnung der Registrierung aufzuheben, oder controls: [], um ihre
Steuerelemente zu löschen. Rufen Sie dispose() auf und entfernen Sie Ereignis-Listener, wenn Sie die
Integration entfernen. Die Bereinigung muss auch die reguläre Darstellung wiederherstellen: dispose()
entfernt nur die Steuerelementregistrierung und macht Ihre Vorschauänderungen nicht rückgängig. Das Abstandsbeispiel
entfernt seine Inline-Überschreibung, um den ursprünglichen CSS-Wert wiederherzustellen. Beide Methoden
kehren synchron ohne Wert zurück. Aktualisierungen wirken sich auf
künftige Auswahlen aus; gespeicherte Annotationen behalten ihre erfassten Steuerelemente und ihr Ziel.
Steuerelementereignisse richten sich an das von der Annotation erfasste Element. Das Aktualisieren der Ziele einer Registrierung leitet bestehende Annotationen nicht um. Zurücksetzungsereignisse können weiterhin auf einem entfernten Element ausgelöst werden; ein Listener auf dessen früherem übergeordnetem Element empfängt sie daher nicht.
Canvas-Objekte auswählbar machen
Eine Annotationsfläche ermöglicht Ihrer Anwendung, einzelne Objekte zu identifizieren, die
innerhalb eines Canvas gezeichnet sind. Registrieren Sie das Hostelement mit registerSurface() und stellen Sie
eine hitTest-Funktion bereit, die ein Objekt mit einer stabilen id oder null für
leere Bereiche zurückgibt.
Das Hostelement muss ein mit dem DOM verbundenes HTML-Element außerhalb des Shadow DOM in einem sicheren Dokument der obersten Ebene sein. Die Flächenregistrierung wird innerhalb eines iframe nicht unterstützt.
Dieses Beispiel zeichnet einen Umsatzbalken und macht ihn auswählbar. Platzieren Sie das Skript nach dem Canvas:
<canvas id="revenue-canvas" width="480" height="240">
Revenue this quarter: $120,000.
</canvas>const canvas = document.getElementById("revenue-canvas");
const context = canvas.getContext("2d");
const bar = { x: 40, y: 60, width: 320, height: 100 };
function drawRevenue(highlighted = false) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "#2563eb";
context.fillRect(bar.x, bar.y, bar.width, bar.height);
if (highlighted) {
context.strokeStyle = "#111827";
context.lineWidth = 3;
context.strokeRect(bar.x, bar.y, bar.width, bar.height);
}
}
drawRevenue();
const surface = document.oai?.annotation?.registerSurface?.({
element: canvas,
hitTest({ clientX, clientY }) {
const bounds = canvas.getBoundingClientRect();
const scaleX = bounds.width / canvas.width;
const scaleY = bounds.height / canvas.height;
const rect = {
x: bounds.left + bar.x * scaleX,
y: bounds.top + bar.y * scaleY,
width: bar.width * scaleX,
height: bar.height * scaleY,
};
if (
clientX < rect.x ||
clientX > rect.x + rect.width ||
clientY < rect.y ||
clientY > rect.y + rect.height
) {
return null;
}
return {
id: "revenue-this-quarter",
name: "Revenue this quarter",
role: "chart-bar",
metadata: { Metric: "Revenue", Value: 120000 },
rect,
};
},
renderSelection({ hoveredId, selectedId }) {
drawRevenue(
hoveredId === "revenue-this-quarter" ||
selectedId === "revenue-this-quarter"
);
},
});Wenn Sie im Annotationsmodus den Zeiger über den Balken bewegen, wird er hervorgehoben. Durch seine Auswahl wird eine Annotation mit dem Namen des Objekts, Metadaten und einem Screenshot der Auswahl geöffnet.
Halten Sie IDs innerhalb einer Fläche stabil. Der optionale name-Wert ist für den Benutzer sichtbar;
role liefert eine kurze semantische Beschreibung. Die optionale Angabe rect verwendet CSS-Pixel
relativ zum sichtbaren Seitenbereich, passend zu clientX und clientY. Rechnen Sie Szenenkoordinaten um
und berücksichtigen Sie dabei Skalierung, Verschiebung und Zoom.
hitTest kann ein Promise zurückgeben und erhält ein AbortSignal als signal, um
überholte Arbeit abzubrechen. Der Browser wartet 250 Millisekunden, bevor er
auf die DOM-Auswahl zurückfällt. Auch bei Fehlern und ungültigen Ergebnissen fällt er darauf zurück. Geben Sie
null explizit zurück, wenn die Trefferprüfung erfolgreich war, aber kein Objekt gefunden wurde.
Abgebrochene Arbeit muss ihr Promise trotzdem erfüllen oder ablehnen. Der Browser erlaubt
nur einen gleichzeitig laufenden hitTest-Callback und hält diesen Platz belegt, bis das Promise
abgeschlossen ist, auch nach einem Abbruch oder einer Zeitüberschreitung. Wenn ein Worker die Auswahl verarbeitet,
schließen Sie das ausstehende Promise ab, wenn seine Arbeit abgebrochen wird; das Verwerfen einer abgebrochenen Worker-Antwort
kann spätere Canvas-Auswahlen blockieren.
Verwenden Sie den optionalen renderSelection-Callback für anwendungsspezifische Rückmeldungen.
Löschen Sie die Rückmeldung, wenn beide IDs null sind. Rufen Sie surface?.invalidate() nach dem
Verschieben von Objekten oder dem Ändern des Zooms und surface?.dispose() beim Entfernen der
Integration auf. Beide kehren synchron ohne Wert zurück.
Canvas-Objekten Steuerelemente hinzufügen
Registrieren Sie benutzerdefinierte Steuerelemente auf dem DOM-Element der Fläche. Gezeichnete Objekte, in der API als virtuelle Objekte bezeichnet, verwenden Ihre benutzerdefinierten Steuerelemente; integrierte CSS- und Textsteuerelemente gelten für sie nicht.
Verwenden Sie bei mehreren Objekten renderSelection, um die Steuerelemente des Hosts zu aktualisieren, wenn sich
selectedId ändert, bevor der Browser die Annotation erfasst. Steuerelementereignisse
enthalten detail.virtualTarget: { surfaceId, targetId }. Leiten Sie jedes Ereignis
anhand dieser erfassten Identität und ihres callback weiter, nicht anhand der aktuellen
Auswahl. targetId entspricht der id aus hitTest; surfaceId identifiziert die
Flächenregistrierung des Browsers. Reguläre DOM-Ereignisse enthalten kein virtualTarget.
Vorschau-, Vergleichs- und Zurücksetzungsereignisse behalten die Identität des ursprünglichen Objekts bei, nachdem ein anderes Objekt ausgewählt wurde. Beim erneuten Öffnen einer gespeicherten Annotation wird keine erneute Trefferprüfung durchgeführt, um ihr erfasstes Objekt oder ihre Metadaten zu ersetzen.
Den Annotationsmodus steuern
Verwenden Sie toggle(), um einen Moduswechsel anzufordern, isActive(), um den bestätigten Zustand zu lesen,
und das oaiannotationmodechange-Ereignis des Dokuments, um Ihre Benutzeroberfläche synchron zu halten.
Prüfen Sie für ältere oder nicht unterstützte Browser die Verfügbarkeit beider Methoden. Fügen Sie diese Schaltfläche hinzu
und führen Sie das Skript aus, nachdem sie vorhanden ist:
<button id="toggle-annotations" type="button" hidden>
Enter annotation mode
</button>const button = document.getElementById("toggle-annotations");
const annotation = document.oai?.annotation;
function renderMode(active) {
button.textContent = active
? "Exit annotation mode"
: "Enter annotation mode";
}
const onModeChange = (event) => renderMode(event.detail.active);
const onClick = () => annotation.toggle(!annotation.isActive());
if (
typeof annotation?.toggle === "function" &&
typeof annotation?.isActive === "function"
) {
document.addEventListener("oaiannotationmodechange", onModeChange);
button.addEventListener("click", onClick);
renderMode(annotation.isActive());
button.hidden = false;
}
function cleanupAnnotationButton() {
document.removeEventListener("oaiannotationmodechange", onModeChange);
button.removeEventListener("click", onClick);
button.hidden = true;
}toggle() kehrt den Modus um. Übergeben Sie true, um sicherzustellen, dass er aktiviert ist, oder false, um sicherzustellen,
dass er deaktiviert ist. Wiederholte Anfragen mit demselben booleschen Wert sind idempotent. Die Übergabe von
true erhält einen aktiven Editor oder eine ausstehende Aktivierung; false bricht
eine ausstehende Aktivierung ab und verwendet den normalen Beendigungsablauf.
Rufen Sie toggle() aus einer laufenden Benutzerinteraktion auf. Sein synchrones { accepted }-Ergebnis
bestätigt die Anfrage, nicht einen tatsächlich erfolgten Moduswechsel. Die Prüfungen der
Voraussetzungen durch den Browser können die Änderung weiterhin verhindern. Lesen Sie den Zustand aus isActive()
und dem Ereignis, wie im Beispiel gezeigt.
isActive() benötigt keine Benutzergeste. Der Browser aktualisiert den Wert, bevor er
oaiannotationmodechange auslöst, dessen event.detail.active ein boolescher Wert ist. Der Browser
sendet weder ein anfängliches Ereignis noch ein Duplikat, wenn das Erzwingen eines Zustands keine Änderung bewirkt. Initialisieren Sie Ihre Benutzeroberfläche daher
über den Getter. Wird der Zugriff bei aktivem Modus widerrufen, meldet ein abschließendes Ereignis
active: false, und ein beibehaltener Getter gibt false zurück.
Der Annotationsmodus fängt Seitenklicks ab. Halten Sie die Leertaste gedrückt, um Seitensteuerelemente zu verwenden,
einschließlich Ihrer Schaltfläche zum Beenden, oder beenden Sie den Modus über die Annotationsoberfläche des Browsers.
Das bloße Gedrückthalten der Leertaste lässt isActive() auf true. Die API unterstützt kein
oai-annotation-ignore oder anderes Attribut, das Klicks durchlässt.
Beim Beenden wird der Editor geschlossen, und gespeicherte Annotationen bleiben erhalten, ohne abgesendet
oder in das Eingabefeld verschoben zu werden. Rufen Sie cleanupAnnotationButton() auf, wenn Sie
die Komponente entfernen. Die erfasste API-Referenz ermöglicht es der Bereinigung, Listener zu entfernen,
auch wenn der Namensraum nicht mehr vorhanden ist.
Ihre Integration testen
Öffnen Sie Ihre Website im integrierten Browser der Desktop-App und testen Sie die Funktionen, die Sie hinzugefügt haben:
- Wechseln Sie in den Annotationsmodus und wählen Sie Objekte und Text aus. Prüfen Sie, ob Hervorhebungen, Namen, Bereiche und Metadaten den vorgesehenen Zielen entsprechen.
- Öffnen Sie eine Annotation über die Schaltfläche Ihrer Website. Prüfen Sie das ausgewählte Element oder den Textbereich, den anfänglichen Kommentar und den Editormodus.
- Ändern Sie ein benutzerdefiniertes Steuerelement, vergleichen Sie mit dem Original und löschen Sie die Vorschau. Prüfen Sie, ob Ihre Anwendung den ursprünglichen Zustand wiederherstellt.
- Testen Sie bei Canvas-Inhalten leere Bereiche, Größenänderungen und Szenenänderungen. Wechseln Sie zwischen Objekten und bestätigen Sie, dass Steuerelementereignisse weiterhin das erfasste Ziel aktualisieren. Brechen Sie eine asynchrone Trefferprüfung ab und bestätigen Sie, dass spätere Auswahlen weiterhin funktionieren.
- Speichern, öffnen und bearbeiten Sie eine Annotation über die Anhangsvorschau des Eingabefelds. Prüfen Sie, ob sie ihre Steuerelemente und ihr Ziel beibehält und ob durch ihr Entfernen jede Vorschau gelöscht wird.
- Senden Sie eine Annotation mit einer Nachricht. Bestätigen Sie, dass ChatGPT den
ausgewählten Inhalt, die Metadaten und die angeforderten Werte erhält, einschließlich sichtbarer Auswahlbeschriftungen
und unveränderter Auswahlentscheidungen bei Steuerelementen, die
currentValueweglassen. - Öffnen Sie die Website in einem Browser ohne die API und überprüfen Sie, ob normale Interaktionen weiterhin funktionieren.
Um Aktionen bereitzustellen, die ChatGPT auf Ihrer Website ausführen kann, fügen Sie Website-Tools (WebMCP) hinzu. Annotationen bringen die Auswahl und das Feedback der Person in die Unterhaltung; Website-Tools ermöglichen es dem Agenten, auf Grundlage dieses Kontexts über die vorhandenen Funktionen Ihrer Anwendung zu handeln.