Appearance
功能规格说明:Webview 链接解析
创建日期:2026-08-21
最近更新:2026-09-21(围栏代码块内的裸 URL 也提升为可点击链接,推翻此前「仅行内代码」的范围)
本规格覆盖 VS Code / JetBrains / Desktop 共享 webview(
packages/webview)中链接的解析与点击行为,包括消息 markdown 渲染与 bash 命令输出。链接点击后的宿主路由(desktop 的 localhost 预览面板分流)见 桌面端原型预览,此处不重复。
用户场景与测试 (必填)
用户故事:行内代码中的链接可点击(优先级:P1)
作为用户,我希望助手文本 markdown 中位于行内代码(反引号)里的 http(s) 链接也能像普通链接一样被解析并点击打开,以便 agent 用代码样式展示 URL 时仍可直接访问,无需手动复制。
为什么是这个优先级:agent 输出 URL 时常以反引号包裹(避免被 markdown 误处理),当前这类 URL 渲染为纯文本代码、不可点击,是高频打断阅读的场景。
独立测试:渲染包含 `https://example.com/a/b` 的助手 markdown 文本,验证其保留代码样式(等宽字体 + 底色)同时渲染为可点击链接,点击行为与普通链接一致。
验收场景:
- 假设助手文本含行内代码
`https://example.com/a/b`,当渲染时,则保留代码样式(等宽字体 + 底色),同时渲染为可点击链接;点击行为与普通链接一致——desktop 上 localhost 链接在预览面板打开、其余链接用系统浏览器,IDE 上按原生链接处理。 - 假设行内代码内容不是合法 http(s) 链接(如
`var x = 1`、`www.example.com`(无协议)、相对路径`/foo`),当渲染时,则保持纯代码样式,不可点击。 - 假设行内代码内是
[text](url)形式的 markdown 链接语法原文,当渲染时,则保持代码原文展示,不按链接语法解析——仅提升裸 URL。 - 假设行内代码 URL 首尾带常见标点(如
`https://example.com.`或`(https://example.com)`),当渲染时,则链接可点击,且首尾标点不进入链接目标。 - 假设行内代码内容为
javascript:等非 http(s) 协议,当渲染时,则不得生成链接。
用户故事:围栏代码块中的 URL 可点击(优先级:P1)
作为用户,我希望助手在围栏代码块(```)里打印的 http(s) 地址(本地服务/预览地址、文档或 PR 链接等)也能像正文里的链接一样点击打开,以便 agent 用代码块展示地址(避免被 markdown 误处理、也便于整段复制)时我仍能直接点开,不必手动复制到浏览器。
为什么是这个优先级:agent 常把服务地址单独放进代码块(起本地服务后的 http://127.0.0.1:8097/、文档链接),这是点开频率最高的形态之一;此前这类地址渲染为纯文本、完全不可点击(用户 2026-09-21 报告),与行内代码通道的既有能力不一致。
独立测试:渲染正文为一个只含 http://127.0.0.1:8097/ 一行的围栏代码块,验证该地址渲染为可点击链接、代码块其余原文(换行与缩进)不变,点击行为与消息文本链接一致。
验收场景:
- 假设代码块内一行是裸 http(s) URL(如
http://127.0.0.1:8097/、https://example.com/docs),当渲染时,则该地址渲染为可点击链接,代码块其余内容(换行、缩进、语言类名)保持原样;点击行为与消息文本链接一致——desktop 上 localhost 链接在预览面板打开、其余链接用系统浏览器,IDE 上按原生链接处理。 - 假设 URL 出现在代码行内部(如
curl http://127.0.0.1:3000/health、"url": "https://example.com/api"),当渲染时,则仅 URL 部分可点击,两侧引号与其余代码文本保持原样、不进入链接目标。 - 假设代码块内 URL 首尾带标点或后紧跟全角括号注释(如
http://127.0.0.1:8097/(本地预览)),当渲染时,则链接目标止于标点之前,标点及其后注释文本照常可见(与正文同一终止规则)。 - 假设代码块内容是
javascript:、file:等非 http(s) 协议或 HTML 片段(<div>&</div>),当渲染时,则不生成链接,文本完整转义后按原文展示。 - 假设代码块内不含 URL(
npm run build、var x = 1),当渲染时,则保持原文,不生成链接;其中文件路径部分仍按 文件路径链接 规则可点击。
用户故事:裸 URL 后紧跟全角标点时链接正确终止(优先级:P1)
作为用户,我希望消息文本里的裸 URL 后面紧贴中文标点或全角括号时(如 https://github.com/netease-lcap/wave-agent/pull/2217(commit 说明、https://example.com/b(中文说明)后),链接目标止于标点之前、其后的文字作为正文正常显示,以便中文写作习惯下(URL 后直接接括号注释、不空格)链接依旧指向正确地址,注释文字也不会被吞掉或丢失。
为什么是这个优先级:中文文本里 URL 后紧跟「(说明)」而中间不打空格是高频写法;当前实现只在空白分隔 token 的尾部剥离标点,URL 后的全角括号及其后正文会被整体吞进链接目标(点击打开带 %EF%BC%88 的错误地址),或在 bash 输出通道整段注释被丢弃。
独立测试:渲染含 https://example.com/b(中文说明)后 的助手消息,验证链接目标为 https://example.com/b、(中文说明)后 作为正文可见。
验收场景:
- 假设消息文本为
https://github.com/netease-lcap/wave-agent/pull/2217(commit 说明(全角开括号后直接接正文、中间无空白),当渲染时,则链接目标止于/pull/2217,(commit 说明作为正文显示。 - 假设消息文本为
https://example.com/b(中文说明)后,当渲染时,则链接目标为https://example.com/b,(中文说明)后整体作为正文显示(既不进链接目标,也不被丢弃)。 - 假设 URL 后紧贴其他全角标点(如
https://example.com,见说明、访问 https://example.com。),当渲染时,则链接目标止于标点之前,标点及其后文本保持可见。 - 假设 URL 自身含合法字符(
_、#frag、查询串中的中文如?q=你好、成对 ASCII 括号如/foo(bar)),当渲染时,则链接目标完整保留,不受本规则影响。 - 假设 bash 命令输出中的 URL 后紧跟全角括号(如
Server at http://localhost:8000(说明)),当渲染时,则与消息文本同规则:链接目标止于全角标点之前,标点及其后文本保持可见。
用户故事:bash 命令输出中的 URL 可点击(优先级:P1)
作为用户,我希望 bash 命令输出(.bash-command-output)中的 http(s) URL 被解析为可点击链接,且点击行为与消息文本链接一致(desktop 上 localhost 链接在预览面板打开、其余链接用系统浏览器,IDE 上按原生链接处理),以便运行本地服务或查看命令日志时直接点击访问,无需手动复制。
为什么是这个优先级:运行 python -m http.server、npm run dev 等命令时,输出中的 http://localhost:8000/ 类地址是高频操作目标;当前 bash 输出为纯文本、不可点击,用户只能复制粘贴。
独立测试:渲染包含裸 URL(如 Server running at http://localhost:8000/)的 bash tool result,验证 URL 渲染为可点击链接、其余文本保持原样,点击行为与消息文本链接一致。
验收场景:
- 假设 bash 命令输出含裸 http(s) URL(如
Server started at http://localhost:8000/),当渲染时,则 URL 渲染为可点击链接,其余文本保持原样;点击行为与消息文本链接一致——desktop 上 localhost 链接在预览面板打开、其余链接用系统浏览器,IDE 上按原生链接处理。 - 假设 URL 首尾带标点(如
visit https://example.com.或(https://example.com)),当渲染时,则链接可点击,且首尾标点(含中文标点)不进入链接目标;URL 后紧跟括号注释(如见 https://example.com(帮助))时注释文本保持可见。 - 假设输出含
javascript:、file:等非 http(s) 协议、<script>等 HTML 片段或&、<等需转义字符,当渲染时,则不生成链接,非 URL 文本经 HTML 转义后按原文展示,无注入风险。 - 假设输出为纯文本无 URL(如错误信息),当渲染时,则保持原样展示,渲染路径无行为变化。
- 假设命令输出为多行且部分行含 URL,当渲染时,则仅含 URL 的行内生成链接,其余行保持原样,换行结构不变。
边界情况
- bash 命令输入行(
.bash-command-input)里的 URL 怎么办? 不处理——仅链接化输出(result),命令本身保持代码样式原文。命令是 agent 执行的代码而非用户阅读的地址。 - 其他工具 result(
.result-raw、.lsp-output等)里的 URL 怎么办? 不在本次范围内,保持纯文本;如后续需要可复用同一链接化函数扩展。 - 行内代码内含多个 URL(如
`https://a.com https://b.com`)怎么办? 内容整体不是单个 URL,保持代码原文、不生成链接,避免歧义。 - 围栏代码块中的 URL 怎么办? 提升为可点击链接(用户 2026-09-21 口径,推翻此前「仅行内代码、代码块保持原文」的范围):代码块内按空白分词,逐 token 切出其中的裸 http(s) URL 提升为链接,token 内其余部分保持代码原文(含文件路径识别,见 文件路径链接);mermaid 代码块渲染为图表,不参与。与行内代码通道的差别只在粒度——行内代码要求整串就是一个 URL,代码块是按 token 切分后逐段提升。
- URL 内部含全角标点怎么办? 一律按终止符处理——全角标点在 URL 中本就应百分号编码,中文语境下它更像是正文分隔符;因此把 URL 候选截断在第一个全角标点之前。ASCII 括号不受影响(成对是 URL 内容,如
/wiki/Hello_(disambiguation))。 - 推理(reasoning)文本块中的行内代码怎么办? 与助手文本一致——共用同一 markdown 渲染路径,行为自然对齐。
- 安全如何保证? 仅 http(s) 协议被提升为链接,
javascript:等危险协议不生成链接;非 URL 文本在注入前完整 HTML 转义;渲染结果仍经 DOMPurify 过滤。