多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Warp MCP 工具调用 JSON 树形渲染(APP-2527):从扁平 JSON 到可交互可折叠的通用 Tree 组件

Warp MCP 工具调用 JSON 树形渲染(APP-2527):从扁平 JSON 到可交互可折叠的通用 Tree 组件 桌面应用开发者工具人工智能AI 应用AI Agent代码智能体【免费下载链接】warpWarp is an agentic development environment, born out of the terminal.项目地址https://gitcode.com/GitHub_Trending/wa/warp点击查看免费下载导读本指南围绕 Warp 开源仓库中 specs/APP-2527/PRODUCT.md 与 specs/APP-2527/TECH.md 两份规格文档展开介绍 Warp 将 MCPModel Context Protocol工具调用的请求参数与响应结果从单一的 pretty-print JSON 文本升级为带 chevron 折叠展开、按值类型着色、可长字符串省略、可右键复制 JSON的交互式树形视图的完整设计与落地过程。阅读本文后你将掌握该功能的全部行为规格PRODUCT 层面、组件与数据管道的架构决策TECH 层面以及当前仓库中JsonTreeView组件、McpRenderable归一化、JsonTreeState展开状态管理等关键实现细节可作为复用该组件或实现同类 JSON 树形 UI 的直接参考。一、背景为什么 MCP 工具调用详情需要一棵 JSON 树在 Warp 的 Agent UI 中当 Agent 调用一个 MCP 工具时展开工具调用详情目前展示的是单一的、等宽字体、pretty-printed 的 JSON 字符串——请求参数和响应结果被拼进同一个String放在同一个Text元素里。问题在于字段一多就难以扫读没有办法折叠掉不感兴趣的子对象键key与值value之间没有视觉区分长字符串值文件内容、日志、base64、堆栈信息会把视图高度撑爆淹没其余结构。用户需要快速理解向工具发送了什么、工具返回了什么而扁平 JSON 无法满足这一点。于是 APP-2527 的目标被定义为在 Agent UI 中将 MCP 工具调用的 JSON 请求参数与 JSON 响应渲染为可交互、可折叠的树带 chevron 展开器与主题驱动的键/值着色替代当前的扁平 pretty-printed JSON blob长字符串默认省略、可原地展开底层 JSON 树组件设计为通用的、可复用的 UI 组件。技术侧TECH.md进一步明确了替换范围RequestedCommandView::render的should_render_mcp_content分支正是被替换的代码块当前仓库对应 app/src/ai/blocklist/inline_action/requested_command.rs 中 1631 行起的相关逻辑。折叠后的 header 行一行MCP Tool: name摘要、accept/reject 操作、以及所有非 MCP 动作渲染shell 命令、文件编辑等均保持不变。二、行为规格PRODUCT 层面全景2.1 适用范围与显示时机树形渲染只作用于MCP 工具调用在 Agent 块列表中的展开详情——请求参数与响应体都用树来展示它替换的是 MCP 工具调用当前单一可选中 pretty-printed JSON 文本不改变折叠态的 header 摘要行、接受/拒绝控件以及任何非 MCP 动作渲染树只在 MCP 工具调用详情展开时显示与今天的MCP 内容仅在动作 header 展开时出现行为一致折叠 header 即隐藏树。2.2 Request 与 Response 两个分区展开后详情首先显示请求参数的树树的根节点就是工具的参数对象传给工具的 JSON一旦响应可用详情在请求树下方再显示响应树并以清晰的视觉/标签分隔如Request与Response标签加分隔线响应到达前只显示请求若工具调用仍在等待阻塞等待批准或正在运行请求参数一旦已知就立刻渲染请求树响应分区在结果到达前不显示。当前仓库实现里请求区与响应区分别调用render_json_tree并传入Some(Request)/Some(Response)标签两个分区共用一棵tree_column布局中间以Container的padding_top(8.)作视觉分隔见 requested_command.rs。2.3 树结构与展开交互每个 JSON 值渲染为以下类型之一对象{}、数组[]、字符串、数字、布尔、null。核心交互规则对象/数组是可折叠节点左侧渲染 chevron 展开器折叠时右指▶展开时下指▼标量字符串、数字、布尔、null无 chevron 且不可折叠长字符串除外可折叠节点的行按序展示chevron → 键对象成员或索引数组元素→ 类型/大小注解注解格式为{} 4 keys、{} 1 key、[] 3 items、[] 1 item、[] 0 items、{} 0 keys。注解计数是传达节点非空的唯一机制折叠行上不显示子键/子值预览点击可折叠节点行的任意位置chevron 或标签即可切换展开/折叠切换一个节点不会改变任何兄弟、祖先或后代节点的状态展开时子节点比父节点缩进一级垂直堆叠、每节点一行缩进深度逐级递增保证结构一目了然对象的子行显示key: value数组的子行显示index: value0 基标量子节点把值内联在同一行对象/数组子节点渲染为嵌套可折叠节点空对象渲染为{} 0 keys、空数组渲染为[] 0 items无 chevron、不响应点击、永不展开为空体。2.4 默认展开状态工具调用详情首次渲染时所有节点默认全部展开让用户立刻看到完整结构树体可滚动且有高度上限大树不会把后续块挤出屏幕没有基于节点数的自动折叠上限无论树多大默认全开展开状态是每个工具调用详情视图的局部状态对话保持打开期间持久折叠再展开动作 header 会恢复该工具调用上次的逐节点展开状态而非重置为默认无需跨应用重启或对话重载持久化若工具调用响应在 header 折叠时到达响应数据被保留展开 header 会同时显示请求与响应两棵树不因 header 折叠而丢失任何数据树体在超过动作详情容器高度时垂直滚动树体施加最大高度上限与命令编辑器主体的现有 max-height 上限一致完全展开的树不会把后续块挤出屏幕滚动树不干扰外层块列表的滚动。当前仓库实现中树体被包装在with_max_height(MAX_EDITOR_HEIGHT)MAX_EDITOR_HEIGHT: f32 500.0的容器中并用NewScrollable::vertical(...)支持独立滚动见 requested_command.rs 与 requested_command.rs。2.5 类型着色Typed Colors键以及每种标量值类型渲染为视觉上互不相同的颜色全部取自当前激活的 Warp 主题不硬编码颜色至少以下类别彼此可区分、且与正文文本可区分对象/数组的键及数组索引、字符串值、数字值、布尔值、null 值容器类型/大小注解{} 4 keys使用弱化/次要文本色颜色随主题自适应在亮色与暗色主题下对详情背景保持可读颜色派生自主题 token切换主题无需重启即更新标点/结构字形花括号、方括号、冒号、字符串引号采用一致、可读的处理绝不能与值混淆。当前仓库的JsonTreeColors::from_theme完整实现了该映射见 app/src/ui_components/json_tree.rs类别颜色来源key / index键与数组索引theme.ansi_fg_cyan()string 字符串值theme.ansi_fg_green()number 数字值theme.ansi_fg_yellow()bool 布尔值theme.ansi_fg_magenta()null 值internal_colors::text_disabled(theme, background)注解{} 4 keys与标点internal_colors::text_sub(theme, background)2.6 长字符串省略Long String Elision字符串长度超过阈值单行显示长度时默认省略显示截断预览并以省略号结尾附 chevron或等价展开器提示可展开激活长字符串的展开器可原地显示完整字符串值必要时跨行换行不会折叠或扰动周围节点再次激活则收回为省略预览。长字符串的切换与对象/数组节点展开状态相互独立并遵循与节点展开相同的持久化规则不超过阈值的字符串完整内联显示无展开器多行字符串含换行按长字符串处理折叠预览显示第一行或截断部分加展开器展开显示完整多行内容。当前仓库将阈值定义为pub const LONG_STRING_THRESHOLD: usize 120并实现is_long_string(s) s.len() 120 || s.contains(\n)见 json_tree.rs 与 json_tree.rs。render_long_string_row在折叠态取首行、截断到 120 字符并以…U2026结尾展开态则用ShrinkableText::new换行显示全量文本且展开态文本显式with_selectable(true)以支持选择见 json_tree.rs。2.7 选择、复制与右键上下文菜单用户可在渲染树内选择文本键与值用标准复制快捷键复制复制选区得到选中区域的可见文本无选区时复制为 no-op右键点击树节点行或 Request/Response 分区标签显示至少包含以下项的上下文菜单Copy——复制当前文本选区无选区时置灰禁用Copy JSON——复制以右键节点为根的子树的完整原始 JSON或右键标签时复制整个分区的完整 JSON以 pretty-printed JSON 格式输出对标量节点复制其 JSON 表示Copy JSON 始终复制完整的底层 JSON无论节点当前折叠还是展开——无需先完全展开即可提取子树。当前仓库通过Hoverable::on_right_click捕获行路径将子树用serde_json::to_string_pretty序列化并携带行的SavePositionanchor ID派发ShowMcpContextMenu动作弹出菜单见 requested_command.rs菜单项包括Copy、Copy JSON、CloseMcpContextMenu等动作。2.8 畸形 / 边界数据MCP 工具调用的响应可能不是单一 JSON 对象——可能是结构化内容、一个或多个文本内容项或错误。渲染分别处理结构化/JSON 内容 → 按上述树渲染非合法 JSON 的纯文本内容 → 渲染为字符串值受长字符串省略规则约束而不是失败的/空树错误结果 → 渲染为明确标注的错误消息如Error: message被取消的工具调用 → 渲染为清晰的 cancelled 指示请求参数缺失或为 null无参数的工具调用时请求树渲染为空/null 指示而不是坏节点合法但异常的 JSON 值——空字符串、超大数字、整数化浮点、unicode、嵌套对象数组——渲染时不 panic、不丢数据整值整数参数显示为整数如5而非5.0与工具调用实际派发方式一致重复对象键原始 JSON 中可能出现全部渲染不静默丢弃。当前仓库通过McpRenderable枚举归一化结果Tree(serde_json::Value)/Error(String)/Cancelledmcp_result_to_renderable依次尝试structured_content→ 拼接文本 JSON 解析 → 包成 JSON 字符串值见 requested_command.rs。数字渲染由format_number承担整数值与整数化浮点均输出为整数5.0→53.14→3.14见 json_tree.rs。2.9 流式与一致性约束请求参数仍在流式到达时请求树可随结构增多而更新部分/进行中的结构渲染不得闪烁重置已渲染节点的展开状态展开的 MCP 详情仍位于它今天所在的同一边框动作容器内周边间距、header、footer 行为不变仅正文原 JSON blob改为树header 的键盘 accept/reject/expand 行为不变非 MCP 动作详情命令、编辑、web fetch 等视觉上不受此变更影响。三、技术规格TECH 层面架构决策与设计权衡TECH.md 在关键代码引用的基础上全部锁定在提交46265f4对五个设计问题给出了推荐方案与备选方案的对比分析。3.1 组件归属通用warpui级组件方案 A1推荐A1 推荐新增独立JsonTreeView作为 app 层ui_components中的通用元素避免在warpuicrate 自身引入serde_json依赖。组件接收serde_json::Value、JsonTreeState展开映射、JsonTreeColors预解析主题色以及 toggle/copy 回调返回Boxdyn Element不依赖任何 agent 特定类型A2 备选内联在requested_command.rs中实现。优点是零新增 crate 面、上手快缺点是不可复用、把 MCP 特定逻辑结果解析、整数强转与通用树渲染混在一起推荐理由ReadMCPResourceResult显然是下一个消费方通用组件是恰当的抽象层级agent 代码只调用组件、不包含渲染逻辑且无需 agent 脚手架即可隔离测试。当前仓库落地在 app/src/ui_components/json_tree.rs公开面包括JsonTreeColors、JsonTreeState、LONG_STRING_THRESHOLD、render_json_tree(...)并由 app/src/ui_components/mod.rs 声明json_tree模块。3.2 元素构建递归构建 vs 扁平虚拟化列表方案 B1推荐B1 推荐构建Flex::column行只遍历树中已展开的部分折叠节点只占一行其子树完全跳过B2 备选预遍历可见树为扁平VecTreeRow再用虚拟化滚动容器只渲染视口内的行推荐理由B1 实现简单、与 JSON 递归结构自然匹配、折叠子树零逐节点开销——只要用户不全量展开大载荷也保持快B2 需要warpui目前不存在的虚拟化原语复杂度高而 MCP 载荷很少大到需要它。若真实世界载荷证明有问题可在JsonTreeView内部追加显示前 N 项 …show more上限完全无需改动调用方。3.3 展开状态存储路径键控 vs 节点身份键控方案 C1推荐C1 推荐HashMapVecPathSegment, bool其中PathSegment Key(String) | Index(usize)。VecPathSegment直接派生Hash Eq作为键无需Rc间接层。is_expanded(path, depth)默认规则depth 0 为 true、更深为 falsetoggle(path)翻转C2 备选解析时为每个节点分配稳定整数 IDarena 指针查找 O(1)、结构相同的兄弟节点状态完全独立但流式重新解析会使 ID 失效需要协调步骤保留展开状态推荐理由C1 对流式重解析稳健——同一逻辑节点在字节到达过程中保持展开状态因为给定 JSON 结构位置的路径是确定的结构相同的兄弟对象共享同一路径在实践中无害切换任一兄弟会恢复两者相同状态可接受。当前仓库的JsonTreeState还包含第三个映射string_expansion长字符串展开并额外维护按路径键控的mouse_statesMouseStateHandle缓存——这是 WarpUI 的要求句柄必须创建一次并在多次渲染间复用否则click_count在LeftMouseDown与LeftMouseUp之间会被丢弃点击处理器永不触发见 json_tree.rs 的详细注释。3.4 请求数据流结构化值 vs 重新解析字符串方案 D1推荐D1 推荐在RequestedCommandView上新增mcp_request: OptionMcpRequest字段McpRequest { name: String, args: serde_json::Value }由block.rs的handle_mcp_tool_stream_update在更新command_text的同时把强转后的display_input: serde_json::Value与name一并传入D2 备选渲染时从MCP Tool: name (value)字符串中提取 JSON——格式串不稳定、外层包装使干净提取不可靠且需重新应用整数强转推荐理由D1 无有损字符串往返整数强转直接继承既有coerce_integer_args路径结构化值在调用点已经可用。当前仓库中McpRequest { args: serde_json::Value }定义于 requested_command.rsmcp_request字段在流式更新时被填充self.mcp_request Some(McpRequest { args })见 requested_command.rs。整数强转coerce_integer_argspub(crate)实现在 app/src/ai/blocklist/action_model/execute/call_mcp_tool.rs在 call_mcp_tool.rs 派发前按工具 schema 对参数就地强转并由 execute.rs 与 block.rs 重新导出复用其行为由 call_mcp_tool_tests.rs 的多组用例覆盖。3.5 上下文菜单 / Copy JSON 实现方案 E1推荐E1 推荐使用Hoverable::with_on_right_click其他 inline action 已在使用显示包含 Copy / Copy JSON 的Menu。树中每一行注册自己的右键处理器捕获该行的JsonPathE2 备选在整棵树容器挂一个右键处理器通过命中测试判断点击行——需存储行包围盒命中测试复杂推荐理由E1 与 App 中既有右键菜单模式一致行内捕获的路径使 Copy JSON 能精确复制该行子树。当前仓库的ToggleFn、ToggleStringFn、CopyJsonFn三个回调类型定义见 json_tree.rsCopyJsonFn携带 path、value 与 anchor ID用于把菜单定位到被点击行下方。四、分阶段实施计划Phase 1–3Phase 1 — 通用JsonTreeView组件与单元测试目标交付一个独立、可测试、把serde_json::Value渲染为交互树的组件本阶段不修改任何 agent/MCP 代码。新增文件与公开面与当前仓库实现一致app/src/ui_components/json_tree.rs新——核心组件包含JsonTreeColors、JsonTreeState、LONG_STRING_THRESHOLD与render_json_treeapp/src/ui_components/mod.rs——声明json_tree模块app/src/ui_components/json_tree_tests.rs新#[cfg(test)]——纯逻辑测试覆盖注解格式化{} 0/1/N keys、[] 0/1/N items长字符串检测达到/超过LONG_STRING_THRESHOLD、多行字符串整数渲染整数化浮点 → 整数重复键保留JsonTreeState::toggle独立性切换一路径不改变其他路径空容器不可展开。实际测试文件 json_tree_tests.rs 中的用例如toggle_one_path_leaves_other_paths_unchanged、toggle_nested_path_independent_of_parent、whole_float_displays_as_integer、duplicate_object_keys_not_silently_dropped等与文档逐条对应。Phase 2 — MCP 数据管道结构化值与结果归一化目标把结构化serde_json::Value请求贯穿到RequestedCommandView并把CallMCPToolResult归一化为可渲染形式仍无可见 UI 变化旧Text渲染路径保持激活。变更点requested_command.rs 新增mcp_request、mcp_request_tree_state、mcp_response_tree_state字段与ToggleJsonNode、ToggleJsonString动作经handle_action调用mcp_tree_state.toggle(...)并ctx.notify()block.rs 扩展handle_mcp_tool_stream_update同时传入display_input: serde_json::Value与name填充mcp_requestcommand_text仍保留给折叠 header新增mcp_result_to_renderable归一化助手McpRenderable枚举requested_command.rs。对应单元测试mcp_result_success_with_structured_content_returns_tree、mcp_result_success_with_json_text_content_returns_parsed_tree、mcp_result_success_with_non_json_text_returns_string_tree、mcp_result_error_returns_error_variant、mcp_result_cancelled_returns_cancelled_variant见 json_tree_tests.rs。Phase 3 — 替换渲染主体与上下文菜单目标用JsonTreeView组件替换旧的Textserde_json::to_string_pretty接入上下文菜单并发布。变更点见 requested_command.rs将content_text/ 单一Text替换为Request Response 两个带标签分区含分隔对应行为 4各自调用render_json_tree(...)Request 分区渲染mcp_request.args无请求时显示(no arguments)指示对应行为 29Response 分区仅在action_status.finished_result()存在时出现按McpRenderable分派到树 / 错误标签 / cancelled 标签树体包裹在ConstrainedBox::with_max_height(MAX_EDITOR_HEIGHT)与垂直NewScrollable中实现滚动行为 17SelectableAreamcp_content_selection_handle包裹可滚动树保证文本选择/复制仍可用行为 25右键 Copy JSON 回调按收到的路径遍历serde_json::Value用serde_json::to_string_pretty序列化并写入剪贴板行为 27。五、测试与验证策略TECH.md 给出了完整的测试矩阵不变量测试类型位置注解标签行为 8、12单元json_tree_tests.rsPhase 1切换独立性行为 9、15单元json_tree_tests.rsPhase 1长字符串检测行为 21–24单元json_tree_tests.rsPhase 1整数/异常值行为 30–31单元json_tree_tests.rsPhase 1mcp_result_to_renderable行为 28单元json_tree_tests.rsPhase 2null/缺失请求行为 29单元json_tree_tests.rsPhase 2流式展开稳定性行为 32单元json_tree_tests.rsPhase 2所有视觉/交互行为手动PR 检查清单Phase 3Phase 3 的手动验证清单合并前必查摘要配置本地 MCP server如 filesystem并展开工具调用验证根展开/嵌套折叠/chevron 独立切换/逐级缩进大型嵌套响应下验证 Request/Response 标签与分隔线、全类型着色、亮↔暗主题切换即时变色长字符串文件内容验证省略预览与原地展开超高展开树验证滚动且不把后续块挤出屏幕响应在 header 折叠时到达后验证双树同时显示错误与被取消调用显示标注消息折叠容器上右键 Copy JSON 得到完整 JSONRequest 标签上右键 Copy JSON 得到完整请求 JSON无选区时 Copy 为 no-op 且菜单项置灰跨键/值行的文本选择与复制折叠 header、accept/reject 与非 MCP 动作视觉不变PR 附亮/暗主题展开树截图。六、风险与缓解措施超大载荷性能只渲染展开节点缓解设计 §B1后续可在JsonTreeView内部追加显示前 N / show more上限无需改动调用方SelectableArea与逐行Hoverable的交互这是 Phase 3 最高风险点。每行用Hoverable支持右键把行包进现有SelectableArea可能导致鼠标事件冲突右键处理器先于SelectableArea消费事件或反之。实现者应验证事件传播可能需要在右键路径上恰当使用DispatchEventResult::Consumed防止双重处理并显式测试菜单在文本选区上方打开的场景选区回归现有单Text选区行为成熟把树包进同一SelectableArea/SelectionHandle配合FormattedTextElement保持选区模型不变需在 Phase 3 PR 中请评审者重点关注流式闪烁路径键控状态设计 §C1防止请求参数流式到达时丢失展开状态由单元测试覆盖Copy JSON 剪贴板访问App 其他右键菜单已能写剪贴板此处沿用同一机制。七、后续演进Follow-ups超大根节点的自动折叠行为 14 的开放问题将JsonTreeView复用于ReadMCPResourceResult及其他承载 JSON 的表面Phase 3 发布后的自然下一步消费方若有必要为病态超大展开树引入虚拟化设计 §B2根据真实 MCP 载荷dogfooding 所见确认或更新LONG_STRING_THRESHOLD 120。附关键源码速查表关注点位置通用 JSON 树组件渲染、状态、颜色、回调app/src/ui_components/json_tree.rs组件纯逻辑单元测试app/src/ui_components/json_tree_tests.rsMCP 工具调用详情视图McpRequest、McpRenderable、render_json_tree接入点app/src/ai/blocklist/inline_action/requested_command.rshandle_mcp_tool_stream_update请求数据管道app/src/ai/blocklist/block.rscoerce_integer_args整数强转派发前app/src/ai/blocklist/action_model/execute/call_mcp_tool.rsCallMCPToolResultSuccess / Error / Cancelledcrates/ai/src/agent/action_result/mod.rsWarpThemeANSI 颜色访问器与内部色crates/warp_core/src/ui/theme/color.rs赞分享桌面应用开发者工具人工智能AI 应用AI Agent代码智能体【免费下载链接】warpWarp is an agentic development environment, born out of the terminal.项目地址https://gitcode.com/GitHub_Trending/wa/warp点击查看免费下载相关推荐Warp MCP 工具调用 JSON 树渲染通用可复用 JsonTreeView 组件的设计与落地APP-2527Warp MCP 工具调用 JSON 树渲染通用可复用 JsonTreeView 组件的设计与落地APP 2527 导读 本篇围绕 Warpagenti桌面应用开发者工具人工智能AI 应用AI Agent代码智能体JSON Formatter - 优雅的可折叠JSON可视化工具JSON Formatter 优雅的可折叠JSON可视化工具 JSON Formatter是一个纯JavaScript库专门用于将JSON对象渲染成美观的HT前端UI组件终极JSON可视化神器打造交互式可折叠JSON查看器终极JSON可视化神器打造交互式可折叠JSON查看器 在现代Web开发中JSON可视化已成为数据处理和调试的重要环节。今天介绍一款强大的JSON Forma前端UI组件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表