☰
Warp AI 会话块内联渲染 Markdown 图片与 Mermaid 图表:产品设计、交互规范与实现剖析
2026/10/7 9:31:42 网站建设 项目流程
  • 桌面应用
  • 开发者工具
  • 人工智能
  • AI 应用
  • AI Agent
  • 代码智能体

【免费下载链接】warp

Warp is an agentic development environment, born out of the terminal.

项目地址:https://gitcode.com/GitHub_Trending/wa/warp
点击查看免费下载

导读

在 Warp 的 AI 会话(AI Block List)中,模型回复里出现的alt图片引用和 Mermaid 代码栅栏,过去只能以原始 Markdown 源码的形式展示,用户无法直接看到截图、示意图或流程图的真实视觉结果。本文基于仓库中的产品与技术规格文档(PRODUCT.md、TECH.md),系统讲解"AI 会话块内联 Markdown 图片与 Mermaid 渲染"这一特性的产品目标、三种呈现形态(横向图片行、Images N分组卡片、带标题框的 Mermaid 画布)、回退与复制交互规范,并结合仓库源码剖析其从 Markdown 解析、区块拆分到渲染器与共享 Lightbox 的完整实现链路。读完本文,你将理解该功能在 Warp 中的设计边界(哪些格式支持、相对路径如何解析、何时回退为纯文本),也能掌握其对应的源码位置与验证方式。

背景与问题

AI 回复中携带 Markdown 图片引用和 Mermaid 图表越来越常见。在 AI 会话块中,这类内容作为"源码文本"比作为"渲染输出"更有价值吗?恰恰相反——当用户真正想查看内联的视觉结果时,原始 Markdown 反而更难阅读和扫视。规格文档将其概括为三个具体问题:

  1. 可读性差:AI 回复中的视觉内容(截图、示意图)被显示为原始 Markdown 语法,用户难以直接理解;
  2. 体验不一致:Warp 在应用的其他位置(如 Notebook Markdown)已经支持 Markdown 图片块和 Mermaid 转 SVG 渲染,AI 会话块缺少等效的呈现与交互模型;
  3. 行为未定义:文本与图片混合内容的复制、选区行为此前没有明确规范,需要显式规定。

该功能的目标是让 AI 回复中的截图、示意图、图表在会话块中内联呈现,同时保持可靠的复制行为,且不需要在首个版本中对整个会话块的选区架构做重构。

目标与边界

Goals(要做的)

  • 在 AI 会话块中内联渲染受支持的本地 Markdown 图片;
  • 同时支持绝对路径与相对路径两种图片来源;
  • 相对路径以该 AI 会话块对应会话的当前工作目录为基准解析(而非 Notebook 文件路径或仓库根目录启发式);
  • 在同一发布周期内支持 Mermaid 图表内联渲染;
  • 功能跨 Warp 支持的平台工作,包括 WASM;
  • 图片格式集合与 Warp 现有 Markdown/图片渲染栈保持一致:JPEG/JPG、PNG、GIF、WebP、SVG;
  • 每个成功渲染的文件型图片下方展示其源文件链接;
  • 保持稳定的复制行为,不引入新的跨渲染器选区模型;
  • 允许对渲染后的图片/Mermaid 图表右键复制其底层 Markdown 源码(而非图片字节);
  • 图片缺失、无法解析或不支持格式时,干净地回退为原始 Markdown;
  • 用独立的会话块专属特性开关(feature flag)控制该渲染;
  • 除新开关外还需尊重既有 Mermaid 渲染开关,即会话块内 Mermaid 仅在两个开关同时开启时渲染;
  • 复用以图方式查看 Warp 既有的全屏 Lightbox。

Non-Goals(明确不做)

  • 首个版本不支持远程图片 URL;
  • 首个版本不支持 Markdown data URL 或其他内联编码图片源;
  • 不加入图片编辑、缩放控件、尺寸调整或图片专用工具栏;
  • 不将图片字节复制到剪贴板;
  • 不加入拖放、保存图片、打开图片等操作;
  • 不扩展超出 Warp 现有渲染能力的图片格式;
  • 不允许"先上文件型图片、后上 Mermaid"的拆分发布,两者属于同一实现序列。

用户体验设计

适用范围

该功能适用于渲染 Markdown 内容的 AI 会话块回复,并且要求对以下场景一致生效:

  • 新流式到达的 AI 回复;
  • 从历史记录重新打开(reopen)的已渲染回复;
  • 恢复(restore)的会话视图所展示的相同 AI 块内容;
  • 包括 WASM 在内的所有受支持客户端平台。

支持的来源与格式

首个版本支持两类内联视觉 Markdown 内容:

  1. 指向本地文件的标准 Markdown 图片引用(绝对路径或相对路径);
  2. Markdown 中编写的 Mermaid 图表,由 Warp 在运行时渲染为图片表示。

相对路径的解析基准是 AI 块渲染时记录的会话工作目录。当会话块后续被恢复或重新渲染时,相对路径应再次基于该记录的工作目录重新解析。文件型图片支持的格式与 Warp 共享图片渲染器一致:

格式说明
JPEG / JPG常见位图压缩格式
PNG无损位图格式
GIF支持动图的位图格式
WebP现代 Web 图片格式
SVG矢量图格式

如果文件存在但不属于上述格式,Warp不做降级或尽力渲染,而是像今天一样直接展示原始 Markdown 文本。

文件型图片的两种布局

文件型图片成功渲染后,按其出现形态分为两种布局:

1. 内联图片行(Inline image runs)

当多个被解析器识别的 Markdown 图片引用出现在同一行、仅由空白分隔时,Warp 渲染为横向图片行:

  • 每张图片上方展示各自的可见源路径标签(源码实现中内联行显示的是最终路径段/文件名);
  • 每项保持宽高比,行在回复流中左对齐;
  • 路径标签保留既有的 hover 高亮与点击打开文件行为;
  • 当路径指向 PNG、JPG、GIF、WebP 等二进制文件时,激活路径应使用平台默认打开器,而不是 Warp 编辑器或用户配置的$EDITOR(macOS 上即open)。

2. 块级图片分组(Block-level image groups)

当 Markdown 图片作为独立的块级条目(各自独占一行)出现时,连续成功渲染的图片被分组进一个带边框的卡片:

  • 卡片标题为Images N,N为该分组内成功渲染的图片数量;
  • 卡片中每一行:左侧为方形缩略图,右侧为源路径;
  • 源路径保留与其他文件链接一致的 hover 高亮与点击打开行为;
  • 二进制文件路径用平台默认应用打开;
  • 不支持或无法解析的图片回退为原始 Markdown,不进入分组卡片。

对于成功渲染的文件型图片,Warp 还会在对应布局位置展示源文件链接:链接文本即 Markdown 图片引用中的文件路径/源文本,参与正常的链接高亮与点击行为,并在恢复的会话中与初次渲染时同样可见。

点击放大:复用的全屏 Lightbox

点击渲染后的图片(无论是内联行、分组卡片,还是 Mermaid 图表)都会打开Warp 既有的全屏 Lightbox 覆盖层,而不是新建一次性查看器。关键行为:

  • Lightbox 复用 Warp 其他位置已使用的全屏覆盖处理;
  • 当前 AI 消息包含多个成功渲染的视觉项时,Lightbox 支持按源码顺序在视觉项之间上一条/下一条导航;
  • 对文件型图片,全屏查看器持续展示图片源路径作为描述性文本。

在源码中,Lightbox 由工作区层(WorkspaceAction)驱动:WorkspaceAction::OpenLightbox/UpdateLightboxImage驱动LightboxView(见 app/src/workspace/lightbox_view.rs 与可复用组件 crates/ui_components/src/lightbox.rs),已支持 Escape 关闭、左右键盘导航与前后按钮,会话块渲染器应复用该路径而非另起炉灶。

Mermaid 渲染与双开关门控

Mermaid 图表与文件型图片同属一个功能序列,在 AI 会话块中内联渲染为视觉内容。它要求两个独立条件同时为真:

  • 既有的全局 Mermaid 渲染开关(FeatureFlag::MarkdownMermaid)已启用;
  • 新的会话块图片渲染开关(FeatureFlag::BlocklistMarkdownImages)已启用。

任一开关被禁用时,会话块中的 Mermaid 内容回退为原始 Markdown/源码渲染。用户视角下:

  • AI Markdown 中的 Mermaid 图表以带标题的边框块出现在回复流中;
  • 块使用深色标题处理、Mermaid 专属标题,内部为白色画布承载渲染后的图表;
  • 渲染可异步进行,UI 在生成期间不得阻塞;
  • 点击渲染后的 Mermaid 图表同样进入共享全屏 Lightbox;
  • 同消息多个渲染视觉项时,Lightbox 支持源码顺序的 prev/next 导航;
  • 渲染失败时回退为原始 Mermaid Markdown 源码。

布局与尺寸规范

渲染后的文件型图片与 Mermaid 图表都应保持宽高比、完整可见、不裁剪不失真,具体尺寸取决于呈现形态:

形态尺寸策略
内联图片行中等高度的缩略图,单张宽度由宽高比推导并设上限,保证整行视觉均衡
块级图片分组每行使用方形缩略图槽位
Mermaid带边框块 + 内边距的白色画布承载图表

内联/分组形态是默认的流内呈现。点击渲染图片或 Mermaid 打开共享全屏 Lightbox 作为次要查看模式,不改变内联布局本身。

回退行为:宁可显示源码,不渲染残缺图片

回退行为是可预测且重要的。对文件型图片,以下任一情况发生时,Warp 都应展示原始 Markdown 图片语法(与当前行为一致),而不是渲染错误型图片容器:

  • 路径无法解析;
  • 文件不存在;
  • 格式不支持;
  • 资源加载失败。

对 Mermaid 图表,渲染失败时展示原始 Mermaid Markdown 源码。源码实现上,回退是渲染期局部决策,不修改已存储的 section 载荷,从而避免因瞬时失败而破坏恢复会话的确定性。

选择与复制行为

首个版本不引入跨渲染器类型的混合拖拽选区重构,保持会话块现有文本、代码块、表格的选区行为不变。渲染后的视觉内容通过显式复制通道支持复制:

  • 块级复制动作包含渲染图片与 Mermaid 图表的底层 Markdown 源码;
  • 右键复制渲染图片/Mermaid 图表时,复制该视觉元素对应的底层 Markdown 源码(文件型图片即原始alt引用;Mermaid 即原始 fenced 源码)。

首个版本接受复制时把视觉内容序列化回原始 Markdown,而不是尝试输出富 HTML 或图片剪贴板内容;同时不向剪贴板写入图片字节。

混合内容行为

AI 会话块必须支持以下回复形态:纯文本、单图片、单 Mermaid、多文件型图片、多 Mermaid、以及文本+图片+Mermaid 混合。每个受支持的视觉元素都应在正确的源码位置独立渲染;不支持或无法解析的项保持原始 Markdown 文本,不影响相邻受支持项的渲染。

流式与恢复行为

  • 流式回复:文件型图片在足够多的 Markdown 出现以识别图片引用后即渲染;Mermaid 在足够源码出现以识别并生成图表后渲染;渲染更新不得破坏周边内容或意外清空活动选区。
  • 恢复回复:受支持的图片与 Mermaid 与初次回复视图渲染方式一致;恢复时资源不可用则应用相同回退规则。

技术实现剖析:从解析到渲染

说明:以下实现剖析基于仓库当前源码状态。规格文档所描述的模型(Image/MermaidDiagram section、内联行/分组卡片布局、双开关门控、Lightbox 复用等)均可在源码中找到对应实现,因此本节以"文档设计 + 源码证据"对照的方式展开。

现状:图片为何"消失"

会话块目前通过 app/src/ai/agent/util.rs 中parse_markdown_into_text_and_code_sections(第 35-186 行)对 AI Markdown 做行导向拆分,识别三类内容:普通 Markdown 文本、围栏代码块(含链接代码元数据)、GFM 表格。普通文本由render_rich_text_output_text_section委托FormattedTextElement渲染,而在 crates/warpui_core/src/elements/formatted_text_element.rs 中,FormattedTextLine::Image(_)、Embedded(_)、HorizontalRule均被当作类换行的布局项而非可渲染内容处理——这正是会话块 Markdown 图片一直无法显示的根源。规格文档的定位是:这是对现有基于 section 的会话块渲染器的一次外科手术式扩展,不替换整体 Markdown 渲染架构。

解析层:窄而精确的图片行识别

关键设计约束:会话块不应发明"任意内联图片样式文本都渲染"的宽泛规则。现有markdown_parser的parse_image(crates/markdown_parser/src/markdown_parser.rs 第 352-361 行)只识别独占一行的图片(可选前导空白),段落内联图片(如text img more text)会被当作纯文本——这提供了一种优雅降级。为区分两种布局,实现引入了parse_image_run_line(第 366-384 行):解析整行由若干图片引用构成、彼此仅以空白分隔的场景,返回图片列表;对text img这类混合内容行返回None,仍作为纯文本处理。

对应地,app/src/ai/agent/util.rs 的flush_plain_text_sections(第 215-250 行)逐行扫描纯文本区:

  • 单张图片行 → 生成AIAgentTextSection::Image并标记AgentOutputImageLayout::Block(块级);
  • 同行多张图片 → 生成多个AIAgentTextSection::Image并标记AgentOutputImageLayout::Inline(内联行)。

数据模型:显式保留 Markdown 源码

AIAgentTextSection枚举(app/src/ai/agent/mod.rs 第 1721-1736 行)扩展为五个变体:

pub enum AIAgentTextSection { PlainText { text: AgentOutputText }, Code { code: String, language: Option<ProgrammingLanguage>, source: Option<CodeSource> }, Table { table: AgentOutputTable }, Image { image: AgentOutputImage }, // markdown 图片渲染为视觉块 MermaidDiagram { diagram: AgentOutputMermaidDiagram }, // Mermaid 图表渲染为视觉块 }

对应的载荷结构(第 1710-1719 行附近):

pub struct AgentOutputImage { pub alt_text: String, pub source: String, pub title: Option<String>, pub markdown_source: String, // 保留原始/规范化 Markdown 源 pub layout: AgentOutputImageLayout, } pub struct AgentOutputMermaidDiagram { pub source: String, pub markdown_source: String, }

核心设计选择:在 section 载荷上保留 Markdown 源码,而不是日后从渲染状态重建。这样块级复制/导出精确、右键复制简单、回退渲染简单。markdown_source初始规范化为alt(util.rs 的markdown_source_for_image第 263-269 行复用编辑器栈的format_image_markdown),Mermaid 则规范化为```mermaid\n{source}\n```(markdown_source_for_mermaid第 271-273 行)。

渲染层:section 渲染器的外科手术式扩展

render_text_sections(app/src/ai/blocklist/block/view_impl/common.rs 第 1160 行起)在既有文本/代码/表格渲染模式基础上追加视觉 section 渲染:

  • 遇到AIAgentTextSection::Image时,通过collect_renderable_image_group收集同布局连续的可渲染图片组;
  • 按布局分发:AgentOutputImageLayout::Inline→render_inline_image_section_group(横向行),AgentOutputImageLayout::Block→render_block_image_section_group(Images N卡片);
  • 渲染上下文携带current_working_directory、检测链接、秘密脱敏状态、复制动作工厂与 Lightbox 集合;
  • 每个视觉 section 渲染前都需判定:开关禁用、路径不可解析、资源加载失败或类型不支持 → 渲染markdown_source回退,而不是残缺视觉。

Mermaid 双开关与编辑器助手复用

会话块已嵌入编辑器支持的代码块,app crate 本就依赖warp_editor,因此复用编辑器助手不会引入新的 crate 依赖边:

  • Mermaid 渲染要求FeatureFlag::BlocklistMarkdownImages与FeatureFlag::MarkdownMermaid同时启用(crates/warp_features/src/lib.rs 第 505、519 行分别定义两个开关,文档建议将新开关加入DOGFOOD_FLAGS而暂不加入PREVIEW_FLAGS);
  • Mermaid 的 SVG 内存资源生成与尺寸计算复用 crates/editor/src/content/mermaid_diagram.rs 的mermaid_asset_source,渲染最大宽度取自资源内在尺寸,而不是在会话块渲染器中另调一套 Mermaid 布局助手;
  • 代码栅栏语言判定为 Mermaid 时(is_mermaid_diagram,见 util.rs 第 286 行),section 直接生成MermaidDiagram而非Code。

相对路径解析与工作目录元数据流

相对路径以会话块渲染时的会话工作目录为基准,该数据流在现有架构中已完整存在,不需要新增持久化字段:

  • 会话上下文捕获current_working_directory(app/src/ai/blocklist/controller.rs 第 97-118 行的SessionContext);
  • 持久化的 exchange 存储working_directory(app/src/ai/blocklist/persistence.rs);
  • 恢复的查询历史重新载入该字段(app/src/ai/blocklist/history_model.rs);
  • AIBlock::new已同时接收current_working_directory与shell_launch_data。

实现只需把既有元数据穿线到视觉 section 渲染器:原生平台尽可能规范化(canonicalize)路径,WASM 保留不做规范化的既有行为(见 crates/editor/src/content/edit.rs 的资产源解析规则)。

复制与导出:section 感知的序列化

块级复制/导出路径(app/src/ai/agent/mod.rs 的Display for AIAgentOutputMessage与AIAgentExchange::format_output_for_copy/format_for_copy)对Image与MermaidDiagramsection 从其保留的markdown_source序列化。规则明确:

  • 块级输出复制:图片与 Mermaid section 使用markdown_source;
  • 会话导出始终是 Markdown(非图片字节或 HTML);
  • 渲染图片/Mermaid 的右键复制写入该 section 的markdown_source。

这样无需改动既有选区架构即可获得正确的图片/Mermaid 复制行为。文件链接标签则复用全局输出链接检测管线(DetectedLinksState按 section 索引键控),让路径标签获得常规文件链接高亮与点击行为,二进制文件链接走标准文件打开路径(平台默认应用而非$EDITOR)。

共享 Lightbox 的源码序集合

渲染器在渲染消息时会构建一个按源码顺序排列的可渲染视觉项集合,同时包含成功渲染的文件型图片与 Mermaid 图表。点击任一渲染图片/Mermaid 时,派发WorkspaceAction::OpenLightbox,并携带该集合与被点击 section 的初始索引,从而 Lightbox 的 prev/next 能遍历同一消息中的其余可渲染视觉项(common.rs 的collect_visual_markdown_lightbox_collection与lightbox_image_for_blocklist_image等辅助函数即是该模型的具体实现)。

端到端流程

将产品与实现串起来,一次完整的功能流如下:

  1. AI 后端把 Markdown 文本流式送入AIAgentOutputMessageType::Text;
  2. app/src/ai/agent/util.rs 的parse_markdown_into_text_and_code_sections识别纯文本、代码、表格、解析器可识别的图片与 Mermaid section;
  3. 解析产物以显式Image/MermaidDiagramsection 连同其原始 Markdown 源码存储;
  4. app/src/ai/blocklist/block/view_impl/output.rs 通过既有 section 渲染器渲染新视觉 section(与文本、代码、表格并列);
  5. 视觉 section 渲染器拿到 AI 块存储的current_working_directory与shell_launch_data;
  6. 文件型图片 section 基于该工作目录解析源路径;
  7. Mermaid section 用mermaid_asset_source构建内存 SVG 资源源;
  8. 渲染器从该消息可渲染视觉 section 派生源码序 Lightbox 集合;
  9. 每个视觉 section 依据特性开关与资产/渲染成败,渲染为图片块或回退为纯 Markdown 块;
  10. 文件型图片渲染成功时,在对应布局位置展示可点击/可高亮的文件链接(内联行显示最终路径段,块级行显示完整源路径);
  11. 点击渲染图片/Mermaid 派发WorkspaceAction::OpenLightbox(携带视觉集合与初始索引);
  12. 右键复制渲染图片/Mermaid 写入该 section 的markdown_source;
  13. 点击渲染文件链接继续走共享文件打开流程(二进制标签用平台默认应用而非$EDITOR);
  14. 块级复制与会话导出继续输出 Markdown(视觉 section 用markdown_source);
  15. 会话恢复时,同一 section 载荷使用存储的工作目录元数据与当前开关再次渲染。

风险与缓解

规格文档明确列出了三类主要风险及对策:

风险缓解
选区期望漂移(统一混合选区)产品/技术规格显式声明本变更不新增跨渲染器选区模型;范围聚焦渲染、显式复制与块级复制/导出正确性
解析器范围不匹配完整 Markdown 图片语义新同行解析器仅限"整行由空白分隔的图片引用";不把含![...]的任意散文视为内联图片;完整 CommonMark 内联图片支持留作后续
笔记本与 AI 块的相对路径解析分歧将路径解析抽象为"以基准目录为导向"的助手,笔记本与 AI 块调用方显式使用,并补原生/WASM 覆盖
既有 section 渲染回归在AIAgentOutput::all_text与渲染遍历中保持 section 顺序显式;沿用代码/表格的 per-section 簿记模式;混合内容测试覆盖普通代码块与表格

测试与验证体系

单元测试

  • 扩展 app/src/ai/agent/util_tests.rs:独立图片提取、同行内联图片行提取、多行块级图片提取、图片+表格+文本顺序、Mermaid section 提取;
  • 会话块 Markdown 复制测试:图片 section 序列化为alt,Mermaid section 序列化为 fenced mermaid Markdown;
  • 原生/WASM 相对路径基准目录解析测试;
  • 渲染/助手覆盖:跨跳过空文本 section 的 section 索引保持、Lightbox 索引源码序映射、内联图片文件名标签、无效尺寸的视觉宽度护栏;
  • 共享基元回归:非法图片矩形拒绝、SVG 内在尺寸、单行文本命中测试的 Y 边界。

集成测试

  • 首个集成测试建议为crates/integration/src/test/agent_mode.rs中的test_restored_ai_block_renders_mermaid_and_local_images:通过load_conversation_from_tasks恢复合成ConversationData,将InputContext.directory指向crates/warpui_core/test_data,截取含同行本地图片 Markdown 与 Mermaid 栅栏的真实会话块渲染截图;
  • 后续建议覆盖:文本+链接代码块+Markdown 表格+相对路径图片+Mermaid 的混合回复、混合内容块级复制、恢复会话渲染与回退、禁用开关回退原始 Markdown、共享 Lightbox 初始选中与源码序 prev/next 导航。

手动验证清单(摘要)

  • 相对/绝对路径的 PNG、JPEG、GIF、WebP、SVG 五类图片;
  • 内联同行图片行(每图下方路径标签)、分组块级行(缩略图+路径);
  • 缺失文件与不支持格式的回退;
  • Mermaid 成功/失败回退(新带框样式);
  • 图片与 Mermaid 点击进入共享 Lightbox、内部键盘与按钮导航;
  • 两种视觉的右键复制、含文本/代码/表格/图片/Mermaid 的块级复制;
  • 历史重开后的恢复渲染;
  • WASM 冒烟:路径处理与回退不 panic。

后续规划

  • 若决定扩展markdown_parser,可支持完整的 CommonMark 内联图片语义(当前仅独立行图片);
  • 跨渲染器类型的统一混合内容选区(超出本特性范围);
  • 若 Warp 未来做应用级 Markdown 图片推广,可合并MarkdownImages与BlocklistMarkdownImages开关;
  • 产品若需要,可补充打开/保存/缩放等更丰富的图片交互。

参考文档与关键源码

  • 产品规格:specs/zachlloyd/inline-markdown-images-in-blocklist/PRODUCT.md
  • 技术规格:specs/zachlloyd/inline-markdown-images-in-blocklist/TECH.md
  • Markdown 区块拆分:app/src/ai/agent/util.rs
  • section 数据模型:app/src/ai/agent/mod.rs
  • 会话块渲染器:app/src/ai/blocklist/block/view_impl/common.rs
  • 会话块输出渲染循环:app/src/ai/blocklist/block/view_impl/output.rs
  • Markdown 图片解析器:crates/markdown_parser/src/markdown_parser.rs
  • 特性开关:crates/warp_features/src/lib.rs
  • Mermaid 资产生成:crates/editor/src/content/mermaid_diagram.rs
  • 共享 Lightbox 组件:crates/ui_components/src/lightbox.rs、app/src/workspace/lightbox_view.rs
  • 桌面应用
  • 开发者工具
  • 人工智能
  • AI 应用
  • AI Agent
  • 代码智能体

【免费下载链接】warp

Warp is an agentic development environment, born out of the terminal.

项目地址:https://gitcode.com/GitHub_Trending/wa/warp
点击查看免费下载

相关推荐

上一篇:Knockout.js前端架构设计:大型应用的组织与管理
下一篇:Ink Kit高可用:负载均衡与故障转移策略

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询