标注扩展
浏览器标注 API 让你的网站能够自定义用户选择的内容、 随反馈附带的上下文,以及用户在向 ChatGPT 发送标注前 用于预览更改的控件。
浏览器标注无需更改任何代码即可在你的网站上使用。 用户可以选择页面的一部分、添加评论,并将其作为上下文发送给 Codex 或 ChatGPT Work。
作为开发者,你可以使用浏览器标注 API 提供应用专属的上下文或控件。例如, 你可以在设计系统预览中附加组件变体的预览,帮助开发者了解如何更新网站上的组件。
如需帮助理解浏览器标注 API 或为网站添加标注支持,请安装 Annotations Extensibility 插件。
安装 Annotations Extensibility 插件
试一试
在本指南中体验浏览器标注 API。
- 在 ChatGPT 的内置浏览器中打开此页面。
- 尝试打开此卡片中将出现的建议提示词。
- 进入标注模式,然后选择下方的表格或代码示例,在预定义的布局和主题之间切换。
- 你仍然可以为页面上的任意项目添加标注,并查看默认的标注行为。
在 ChatGPT 内置浏览器中打开此页以体验标注。
选择要自定义的内容
从适合你的网站的集成方式开始:
| 目标 | 集成方式 |
|---|---|
| 将卡片或其他一组元素作为一个对象来选择 | 选择目标 |
| 让用户选择短语或句子 | 文本选择容器 |
| 为所选内容附加更多上下文 | 选择元数据 |
| 通过你自己的按钮打开标注,并附上建议评论 | 标注请求 |
| 从你自己的 UI 请求对特定文本段落的反馈 | 文本范围请求 |
| 在标注打开时显示高级控件 | 编辑器默认设置 |
| 预览应用属性或收集选项 | 自定义控件 |
| 选择画布中绘制的单个对象 | 标注区域 |
| 从你的网站开启或关闭标注模式 | 标注模式控件 |
本指南适用于 ChatGPT 桌面应用的 DevDay 2026 版本及后续版本。
在应用的内置浏览器中,JavaScript API 通过 document.oai.annotation 提供,
适用于 HTTPS 或 localhost 等安全的顶层页面。启用后,
浏览器会在页面脚本运行前安装该 API。请对每个方法进行功能检测,
以支持较旧或不受支持的浏览器,然后在 DOM 元素存在后
初始化集成。无需就绪事件或轮询。
API 方法同步返回,注册句柄可立即
使用。浏览器可以在之后完成标注编辑器的加载。
标注区域的 hitTest 回调可以返回 promise。
自定义选择目标
默认情况下,标注模式从页面的 DOM 中选择元素,优先选择
文本、图像和控件等目标。要让较大的对象可被选择,
请用 oai-annotation-container 标记其所在区域,并用 oai-annotatable 标记
其中可选择的后代元素。
此示例让图表卡片可以作为一个对象被选择:
<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>将指针移到卡片内的任意位置都会高亮显示整张卡片。可选的
oai-annotatable 值为对象提供一个向用户和模型显示的名称。
请选择能区分相邻对象的名称,或省略该值。
容器定义这些选择规则的适用范围。单独添加
oai-annotatable 属性不会改变选择行为。
在容器内,浏览器会选择包含指针下元素的最近的已标记目标。
嵌套容器使用最近的容器。
容器内未标记的区域会创建网页标注;所有容器之外的区域
保持默认行为。
启用文本选择
为区域添加 oai-annotation-container-text,让用户可以在标注模式下
拖动选择文本。该属性无需设置值:
<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>完成非空选择并松开后,会打开文本标注编辑器,其中包含 所选范围及其上下文。仅点击而不选择文本不会创建 标注。按 Esc 键(Escape) 或取消手势会取消选择。
最近的文本选择容器或 DOM 选择容器决定手势的起始行为。
文本容器不使用 oai-annotatable 标记来拾取元素。嵌套
一个 oai-annotation-container 可恢复元素拾取,嵌套文本容器则可
恢复文本选择。如果同一元素同时具有这两个属性,文本选择
优先。
文本选择遵循页面的常规选择规则,可以超出
起始容器。容器不会裁剪所选范围,也不会启用
iframe 内的选择。文本字段仍可选择,但在标注模式下,普通页面点击和
控件的原生操作仍会被阻止。显式的
request() 调用保持现有行为。
为所选内容添加上下文
为已标记的目标添加 oai-annotation-metadata,以包含页面上可能
不可见的上下文。例如,一个虚构的联系人行可以包含
电子邮件地址,用于请求起草邮件:
<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>选择其中任意一行都会选中整个联系人行。元数据会与 标注一同显示,并随标注进入对话。仅包含你 打算同时与用户和模型共享的上下文。发送邮件仍然 需要连接邮件工具。
使用小型、扁平的 JSON 对象,并遵守以下限制:
- 最多六个属性,值可以是字符串、有限数值、布尔值或
null。 - 键最多 64 个字符,字符串值最多 256 个字符。
- 序列化后的对象最多 2,048 字节。
键必须以 ASCII 字母开头,且只能包含 ASCII 字母、数字、 空格、下划线或连字符。词与词之间使用单个空格。不支持嵌套 对象和数组。浏览器会忽略无效的元数据。
你也可以通过 request() 或标注区域的 hitTest
结果提供元数据。
从你的网站打开标注
直接在用户交互中调用 document.oai.annotation.request(target, options),
例如按下按钮时。目标可以是当前文档可见区域内
已连接到文档的 HTML 元素,也可以是
DOM Range。目标无需具有标注
属性。不支持虚拟对象 ID。
网站发起的请求可能需要用户许可;用户可以在 网站工具 > 标注功能 下重新启用已被阻止的标注功能。
将此按钮添加到选择示例中的图表卡片旁,然后在 两个元素都存在后运行脚本:
<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.",
});
});选择进一步解释 会请求浏览器打开标注,其中已选中卡片, 并包含可编辑的评论。用户可以编辑、保存标注,并随 消息发送。打开标注不会向 ChatGPT 发送消息;只有 用户可以提交。
请在当前用户交互期间完成调用。如果先等待网络请求, 可能会丢失该交互状态。
可选的第二个参数支持以下字段:
| 选项 | 行为 |
|---|---|
mode |
使用 "advanced" 打开元素的高级控件,或使用 "default" 采用默认编辑器行为。默认为 "default"。使用 "default" 仍可打开自定义控件;请参阅编辑器默认设置。文本范围仅支持 "default"。 |
enterAnnotationMode |
设置为 true 可进入标注模式,并在取消或发送标注后保持该模式。 |
metadata |
有效的非空元数据会在此次请求中替换目标的 HTML 元数据。对于文本范围,以及目标元素位于 shadow DOM 内的情况,此选项会被忽略。 |
initialComment |
提供可编辑的评论,最多 240 个 UTF-16 代码单元。 |
request() 返回一个包含 accepted 布尔值的对象。请检查
result.accepted,而非结果对象,以确定浏览器是否已接收
并验证请求。它不能确认编辑器是否已打开,也不能确认
用户是否已保存或发送标注。
编辑器加载期间,浏览器可以保留一个已接受的请求。在 有请求待处理、编辑器已打开或 ChatGPT 正在 控制浏览器时,浏览器可能拒绝另一个请求。
请求为文本范围添加标注
传入 DOM Range,可在不改变浏览器文本选择的情况下请求对某段文本的反馈。
此示例选择段落的内容;无需
oai-annotation-container-text 属性:
<p id="draft-passage">Leave more space between separate groups.</p>
<button id="discuss-passage" type="button" hidden>Discuss this passage</button>在两个元素都存在后运行此脚本:
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.",
});
});该范围必须包含当前文档中非空的可见文本,且 所选内容至少有一部分位于页面可见区域内。最多可包含 20,000 个 UTF-16 代码单元。不支持折叠范围、仅含空白字符的文本、所选文本 被隐藏的情况,以及封闭 shadow root 内的范围。
文本范围请求仅使用默认文本编辑器。包含
mode: "advanced" 的请求会被拒绝,请求元数据也会被忽略。已接受的请求
等待编辑器期间,请保持目标文本可用:浏览器会
在打开编辑器前再次检查该范围。文本选择容器则独立
支持用户在标注模式下拖动选择文本。
选择编辑器的默认模式
要让通过浏览器选择 UI 打开的标注立即显示
高级控件,请将此标签添加到页面的 <head> 中:
<meta name="oai-annotation-editor-default-mode" content="advanced" />对于从你自己的 UI 打开的标注,请向
request() 传入 { mode: "advanced" }。使用 mode: "default" 或省略该参数,即可采用默认编辑器行为。
页面的 meta 设置不会覆盖此请求选项。默认模式
并不保证编辑器仅提供评论功能:具有建议初始值的自定义
控件,或省略 currentValue 的控件,都可能打开控件编辑器。
手动调整、折叠和 按住 Option 点击(Option-click) 控件仅在 Codex 或 localhost 上可用。在 ChatGPT 中的托管网站上,已注册的自定义控件 会自动显示,不提供调整 或折叠按钮。页面请求的 高级模式在这些网站上仍然有效。
添加自定义控件
使用 registerControls() 将标注控件关联到一个或多个 DOM
元素。控件可以预览应用属性,例如间距设计变量,
也可以收集要附带在请求中的选项,例如邮件语气。
预览共享的间距设计变量
此示例中的两张卡片使用相同的 CSS 属性:
<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>创建预览后运行此脚本:
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);
}为任一卡片添加标注,并将卡片内边距(像素) 从 16 改为 24。在
ChatGPT 中的托管网站上,控件会自动显示;在 Codex 或
localhost 上,按需选择调整。两张卡片都会更新。标注会记录标签、引用,
以及旧值和新值。清除预览会恢复原来的内边距。
移除组件时调用 disposeAnnotationControls()。
收集选项而不提供预览
使用元数据示例中的联系人行,提供邮件语气选项:
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",
},
],
});此控件无需事件处理程序,因为它不会预览页面
更改。省略 currentValue 会让浏览器包含所选语气,
即使用户保留初始选项也是如此。移除联系人行时
调用 registration?.dispose()。
对于选择控件,预览回调会接收 option.value,例如
"professional"。对于先前选项和当前所选选项,标注历史记录和 ChatGPT 都会收到可见的
option.label,例如 "Professional"。
请使用能说明各个选项的标签;value 中的内部 ID 不会
作为选项文本发送。
配置控件和初始值
使用 controlsMode: "replace" 可仅为已注册的目标显示你的控件,
或使用 "extend" 将其与内置控件一同显示。可选的
controlsHeading 用于为面板命名。浏览器会去除其首尾空白,并接受 1 到 80 个
字符。没有标题时,面板会显示元素的 HTML 标签。
标题不会包含在发送给 ChatGPT 的上下文中。
每个注册最多支持 12 个控件。每个控件都需要 type、可见的
label 和 callback 标识符:
| 类型 | 值 | 附加字段 |
|---|---|---|
color |
十六进制颜色,例如 "#2563eb" |
无 |
range |
数值 | min、max 和 step |
select |
字符串 | options,一个由 { label, value } 对象组成的数组 |
toggle |
布尔值 | 无 |
callback 是字符串标识符,而非 JavaScript 函数。确保它
在注册内唯一,以 ASCII 字母开头,并使用 ASCII 字母、
数字、下划线或连字符。可选的 reference 用于标识
正在更改的属性,并随标签和值一同包含在标注中。
将 currentValue 设置为属性的有效常规值,包括尚未保存的
编辑。不要将预览状态或未完成的输入用作基准。浏览器
使用它进行更改前后对比和重置。应用状态变化时,使用
registration.update({ controls }) 刷新控件的 currentValue
值。更新会影响之后的标注;现有标注保留其
已捕获的值。
设置 defaultValue 可提供建议初始值;在确定控件的初始
状态时,它优先于 currentValue。
如果两者都省略,颜色控件以白色开始,范围控件以最小值开始,
选择控件以第一个选项开始,开关控件则以 false 开始。
将建议值与常规草稿分开。如果更新抛出异常,或
请求失败或返回 accepted: false,请丢弃此次尝试的建议,并
恢复先前的控件和建议状态。请求被接受后,请保留建议:
浏览器可能会先将请求加入队列,再捕获控件。
验证控件和注册
浏览器会根据以下限制验证注册和更新:
| 字段或资源 | 约束 |
|---|---|
| 控件 | 每个注册最多 12 个,且 callback 标识符必须唯一。仅使用为该控件类型定义的字段。 |
| 标签和标题 | 控件标签、选项标签和 controlsHeading 去除首尾空白后必须非空,且最多 80 个 UTF-16 代码单元。控件文本不能包含控制字符或改变文本方向的字符。 |
| 标识符 | callback 去除首尾空白后最多 80 个 UTF-16 代码单元,使用上述格式。reference 长度为 1–80 个字符,允许 ASCII 字母、数字和 _ . / : @ $ # -,不允许空格。 |
| 选择选项 | 1–12 个选项,每个选项的 value 字符串必须不同,且最多 512 个 UTF-16 代码单元。提供的 currentValue 和 defaultValue 必须与某个选项的值匹配。 |
| 范围值 | min、max、currentValue 和 defaultValue 必须是 −10,000 到 10,000 之间的有限数值。必须满足 min < max,step 必须介于 0.001 到 10,000 之间且不大于 max - min,初始值必须在范围内。初始值无需与 step 对齐。 |
| 颜色和开关 | 颜色必须在 # 后使用 3、4、6 或 8 位十六进制数字。开关值必须为 true 或 false。 |
| 目标 | 注册时包含 1–128 个目标条目,全部为当前文档中的元素。更新时可传入 targets: [] 以解除关联。每个文档最多支持 64 个控件注册和 1,024 个注册与目标之间的关联。 |
| 序列化控件 | 包含 controls、controlsHeading 和 controlsMode 的 JSON 载荷必须在 16,384 个 UTF-16 代码单元以内。使用可编码为 JSON 的数据,不得包含函数、符号或大整数。 |
对于无效的定义、目标或超出限制的情况,registerControls() 和 registration.update() 可以
同步抛出异常。在 dispose() 之后进行更新
也会抛出异常。被拒绝的更新会保留先前的注册,包括
其控件和目标。请在调用处处理失败,保持常规
编辑功能可用,并复用或释放你管理的注册,以免超出
限制。
处理预览和重置
oaiannotationcontrolchange 事件从所选元素开始冒泡。其
detail 包含 callback、value 和 action:
| 操作 | 应用所提供的值以 |
|---|---|
preview |
显示所请求的更改。 |
preview-original |
临时显示原始状态以供比较。 |
reset |
在清除预览时恢复原始状态。 |
与间距示例一样,对每种操作都应用所提供的值。确保 处理程序可逆,且可安全地重复调用。预览事件不会请求 永久更改;请通过应用的常规保存流程保存。将 常规草稿、未完成的输入和预览分开,避免无关的编辑 覆盖预览。当用户编辑同一设置时,替换其 预览,并更新基准值以供之后的标注使用。
保留注册句柄以便更新和清理。update() 接受
targets、controls、controlsHeading 和 controlsMode 的任意组合。
省略的字段保留先前的值。例如,替换组件的 DOM
元素时使用 registration.update({ targets: newElement })。
目标集合捕获现有元素,不会跟踪之后
匹配选择器的元素。
传入 targets: [] 可解除注册关联,传入 controls: [] 可清除其
控件。移除集成时,请调用 dispose() 并移除事件监听器。
清理还必须恢复常规渲染:dispose() 仅
移除控件注册,不会撤销你的预览更改。间距示例
通过移除内联覆盖来恢复原始 CSS 值。这两个方法
都同步返回,且不返回值。更新会影响
之后的选择;已保存的标注保留其捕获的控件和目标。
控件事件以标注捕获的元素为目标。更新 注册的目标不会重定向现有标注。重置事件 仍可能在已移除的元素上触发,因此其原父元素上的监听器不会 收到这些事件。
让画布对象可被选择
标注区域让应用能够识别画布内绘制的
单个对象。使用 registerSurface() 注册宿主元素,并提供
一个 hitTest 函数,返回带有稳定 id 的对象,或在
空白区域返回 null。
宿主必须是安全顶层文档中已连接到文档的 HTML 元素,且位于 shadow DOM 之外。不支持在 iframe 内注册标注区域。
此示例绘制一个收入柱形,并使其可被选择。将脚本放在 画布之后:
<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"
);
},
});在标注模式下将指针悬停在柱形上会高亮显示它。选择它会打开 标注,其中包含对象名称、元数据和所选内容的截图。
保持同一标注区域内的 ID 稳定。可选的 name 对用户可见;
role 提供简短的语义描述。可选的 rect 使用
相对于页面可见区域的 CSS 像素,与 clientX 和 clientY 一致。请从场景坐标转换,
并考虑缩放比例、平移和缩放操作。
hitTest 可以返回 promise,并通过 signal 接收 AbortSignal,以
取消已被替代的工作。浏览器会等待 250 毫秒,然后
回退到 DOM 选择。发生错误或结果无效时也会回退。命中测试
成功但没有对象时,请显式返回 null。
被取消的工作仍必须使其 promise 兑现或拒绝。浏览器
同一时间只允许执行一个 hitTest 回调,并会一直占用该名额,直到 promise
完成,即使已经取消或超时也是如此。如果由工作进程处理拾取,
请在其工作被中止时使待处理的 promise 完成;丢弃已取消的工作进程
响应可能阻塞后续的画布拾取。
使用可选的 renderSelection 回调提供应用专属的反馈。
两个 ID 都为 null 时清除反馈。移动对象或更改缩放后
调用 surface?.invalidate(),移除集成时
调用 surface?.dispose()。两者都同步返回,且不返回值。
为画布对象添加控件
在标注区域的 DOM 元素上注册自定义控件。绘制的对象在 API 中 称为虚拟对象,它们使用你的自定义控件;内置 CSS 和文本 控件不适用于这些对象。
对于多个对象,请在 selectedId 变化时,使用 renderSelection 更新宿主的控件,
并在浏览器捕获标注前完成。控件
事件包含 detail.virtualTarget: { surfaceId, targetId }。请使用捕获的身份标识及其
callback 来路由每个事件,而非使用当前
所选对象。targetId 与 hitTest 中的 id 匹配;surfaceId 标识
浏览器的标注区域注册。普通 DOM 事件不包含 virtualTarget。
选择另一个对象后,预览、比较和重置事件仍保留原始对象的身份 标识。重新打开已保存的标注不会重新运行 命中测试来替换其捕获的对象或元数据。
控制标注模式
使用 toggle() 请求模式更改,使用 isActive() 读取已确认的状态,
并通过文档的 oaiannotationmodechange 事件保持 UI 同步。
请对这两个方法进行功能检测,以支持较旧或不受支持的浏览器。添加此按钮,
然后在按钮存在后运行脚本:
<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() 会切换模式。传入 true 可确保模式开启,传入 false 可确保
模式关闭。使用相同布尔值重复请求具有幂等性。传入
true 会保留已打开的编辑器或待完成的激活;false 会取消
待完成的激活,并采用常规退出流程。
在正在进行的用户交互中调用 toggle()。其同步返回的 { accepted }
结果表示已收到请求,并不确认模式已更改。浏览器的
资格检查仍可能阻止更改。与示例一样,从 isActive()
和事件中读取状态。
isActive() 无需用户手势。浏览器会在派发
oaiannotationmodechange 前更新它,后者的 event.detail.active 是布尔值。浏览器
不会发送初始事件,也不会为强制执行但无实际变化的操作发送重复事件,因此请通过读取方法(getter)
初始化 UI。如果在模式启用期间访问权限被撤销,最后一个事件会报告
active: false,保留的读取方法 则返回 false。
标注模式会捕获页面点击。按住 空格键(Space) 可使用页面控件,
包括你的退出按钮,也可以通过浏览器的标注 UI 退出。
仅按住 空格键(Space) 时,isActive() 仍为 true。API 不支持
oai-annotation-ignore 或其他允许点击穿透的属性。
退出会关闭编辑器并保留已保存的标注,不会提交
标注,也不会将其移入消息输入框。移除组件时
调用 cleanupAnnotationButton()。捕获的 API 引用让清理逻辑能够移除
监听器,即使命名空间已经消失。
测试集成
在桌面应用的内置浏览器中打开你的网站,并测试 你添加的功能:
- 进入标注模式,选择对象和文本。检查高亮、 名称、范围和元数据是否与预期目标一致。
- 从网站的按钮打开标注。检查所选元素或 文本范围、初始评论和编辑器模式。
- 更改自定义控件,与原始状态比较,然后清除预览。 检查应用是否恢复原始状态。
- 对于画布内容,测试空白区域、尺寸调整和场景变化。切换 对象,确认控件事件仍会更新捕获的目标。取消 异步命中测试,并确认之后的拾取仍然有效。
- 从消息输入框的附件预览中保存、重新打开并编辑标注。 检查标注是否保留其控件和目标,以及移除标注是否会清除 所有预览。
- 随消息发送标注。确认 ChatGPT 收到
所选内容、元数据和请求的值,包括可见的选择
标签,以及省略
currentValue的控件中未更改的选项。 - 在没有该 API 的浏览器中打开网站,验证常规 交互仍然有效。
要提供 ChatGPT 可在你的网站上执行的操作,请添加 网站工具(WebMCP)。标注将用户选择的内容 和反馈带入对话;网站工具让智能体能够通过 应用的现有功能,基于这些上下文执行操作。