Setup-v2 失败 Tombstone 化改造:从错误消息栏到会话终结墓碑视图)
桌面应用开发者工具人工智能AI 应用AI Agent代码智能体【免费下载链接】warpWarp is an agentic development environment, born out of the terminal.项目地址https://gitcode.com/GitHub_Trending/wa/warp点击查看免费下载导读Warp 是一个源于终端的 agentic 开发环境其云模式Cloud Mode允许用户在云端会话中运行 AI Agent。本文基于仓库中 specs/APP-4459/TECH.md 技术方案讲解 Cloud Mode 设置流程 v2Setup-v2下启动失败spawn failure的 UI 呈现改造当云 Agent 启动失败时不再在 Agent 消息栏渲染红色错误条而是以会话终结墓碑视图conversation-ended tombstone呈现错误、隐藏输入框并抑制 Continue 操作。读者将掌握AmbientAgentViewModelEvent::Failed的完整处理链路、ConversationEndedTombstoneView的数据来源与渲染逻辑以及TaskStatusMessage.error_code对环境设置失败类错误的标记机制。一、改造背景Setup-v2 失败 UI 的痛点在 Cloud Mode 中用户发起一个云 Agent 任务后客户端需要依次完成环境选择、会话建立spawn session等步骤。当会话建立失败时当前的 UI 处理链路是AmbientAgentViewModel::handle_spawn_error将 ViewModel 状态置为Status::Failed { error_message }并发出AmbientAgentViewModelEvent::Failed见 app/src/terminal/view/ambient_agent/model.rs。TerminalView::handle_ambient_agent_event收到Failed事件后移除排队的 prompt block、更新活跃云会话状态、刷新详情面板并通知重绘见 app/src/terminal/view/ambient_agent/view_impl.rs。最终由BlocklistAIStatusBar::render_cloud_mode_setup_terminal_message把ambient_agent_model.error_message()渲染成一条红色错误消息栏见 app/src/ai/blocklist/block/status_bar.rs。这种做法的体验问题在于失败信息出现在Agent 消息栏这一轻量 UI 载体中既没有会话终结的语义会话实际上已经结束了也没有为错误提供足够的展示空间更无法像正常会话终结那样组织标题、错误信息、耗时、积分消耗与 Artifact 等结构化元数据。会话终结墓碑视图既有的正确范式仓库中已经存在一个成熟的会话终结呈现范式TerminalView::insert_conversation_ended_tombstoneapp/src/terminal/view/shared_session/view_impl.rs。它会在会话结束后插入一个ConversationEndedTombstoneView并记录conversation_ended_tombstone_view_id。该视图是一个可承载标题、错误消息、目录、来源、Skill、运行时长、积分、Artifact 按钮以及 Continue 类操作按钮的富内容卡片。关键优势输入框隐藏逻辑已经天然以该墓碑 ID 为开关。TerminalView::is_input_box_visible在 app/src/terminal/view.rs 附近实现当存在conversation_ended_tombstone_view_id时输入框不可见。这意味着只要失败也能走墓碑插入路径输入隐藏就免费获得无需新增独立的输入隐藏状态。二、核心改造方案总览APP-4459 的改动范围被刻意限定在Setup-v2 专属Setup-v1 仍沿用旧的整屏/状态页脚失败 UI两条路径互不影响。整体改造包含四个文件/模块模块位置改动要点TerminalView::handle_ambient_agent_eventview_impl.rs保留既有Failed状态更新与详情面板刷新Setup-v2 启用时追加插入墓碑以conversation_ended_tombstone_view_id防重复插入conversation_output_status_from_conversationapp/src/ai/ambient_agents/mod.rs无已完成根交换且会话状态为Error时回退为AmbientConversationStatus::Error错误载体为RenderableAIError::Otherwill_attempt_resume: false、waiting_for_network: falseConversationEndedTombstoneViewapp/src/terminal/view/shared_session/conversation_ended_tombstone_view.rs从会话状态读取错误展示数据支持hide_continue_actions处理任务前失败pre-task failure特殊文案TaskStatusMessageapp/src/ai/ambient_agents/task.rs新增可选error_code字段serde 映射errorCode与is_environment_setup_failure()辅助方法BlocklistAIStatusBarapp/src/ai/blocklist/block/status_bar.rs移除或按 Setup-v2 门控ambient_agent_model.error_message()分支保留 GitHub 鉴权与取消分支错误来源优先级方案明确了墓碑错误数据的来源优先级第 1 优先级最高AmbientAgentTask.status_message.message—— 有任务支撑task-backed的失败尤其是第三方 harness 运行时本地AIConversation仅作为 UI 载体任务消息才是事实来源会话状态错误conversation status error—— 包括尚未建立任务、但已有活跃本地会话的任务前失败。三、Failed事件的墓碑化插入路径3.1 事件处理保持既有行为追加墓碑插入在handle_ambient_agent_event的Failed分支中原逻辑状态更新 详情面板刷新被原样保留仅增加一行墓碑插入AmbientAgentViewModelEvent::Failed { error_message } { self.pending_cloud_followup_task_id None; self.update_active_ambient_agent_conversation_status( ConversationStatus::Error, Some(RenderableAIError::other(error_message.clone(), false)), ctx, ); if FeatureFlag::CloudModeSetupV2.is_enabled() { self.insert_conversation_ended_tombstone_with_resolved_cta(ctx); } // Refresh the details panel to show failed status if self.is_conversation_details_panel_open { self.fetch_and_update_conversation_details_panel(ctx); } // Re-render to show the error state. ctx.emit(TerminalViewEvent::TerminalViewStateChanged); ctx.notify(); }要点解读状态写入发生在墓碑插入之前Failed处理逻辑先把错误写入会话ConversationStatus::Error再插入墓碑这样墓碑在读取会话状态时能拿到错误信息。这正好对应Setup 失败可能发生在AmbientAgentTask建立之前、但仍有活跃本地AIConversation的场景。RenderableAIError::other(message, false)第二个布尔参数即will_attempt_resume标记此处传false表示该错误不附带自动恢复尝试避免用户误以为失败后还会继续。复用insert_conversation_ended_tombstone_with_resolved_cta该函数内部按HandoffCloudCloud特性与cloud_conversation_continuation_ui_state决定使用何种 CTAContinue in Cloud / Continue locally / 无 CTA见 app/src/terminal/view/shared_session/view_impl.rs。3.2 防重复插入墓碑插入统一收敛在insert_conversation_ended_tombstone_with_ctaif self.conversation_ended_tombstone_view_id.is_some() { self.remove_conversation_ended_tombstone(ctx); } // ... 构造 tombstone_view_handle ... self.insert_rich_content(None, tombstone_view_handle, None, insertion_position, ctx); self.conversation_ended_tombstone_view_id Some(tombstone_view_id);即插入前检查conversation_ended_tombstone_view_id已存在则先移除旧墓碑再插入新墓碑最终只保留一个墓碑富内容视图。这保证即使Failed事件重复到达例如同一 spawn 错误被多次上报用户看到的也始终只有一个墓碑不会堆叠。3.3 输入框隐藏的联动is_input_box_visible已经以墓碑 ID 为开关同时在 app/src/terminal/view.rs 附近输入更新广播也会在存在墓碑且输入隐藏时被抑制let input_is_visible self.is_input_box_visible(model, app); // 如果存在会话墓碑且输入隐藏不应继续广播输入更新 // 因为云 Agent 会话已经结束。 self.conversation_ended_tombstone_view_id.is_none() || input_is_visible因此失败墓碑插入后输入框自动隐藏云会话结束的语义被完整传达。四、conversation_output_status_from_conversation的错误回退conversation_output_status_from_conversation位于 app/src/ai/ambient_agents/mod.rs它从AIConversation推导出面向 ambient agent 的终结状态AmbientConversationStatus。现状逻辑是ConversationStatus::TransientError视为非终结状态返回NoneBlocked、InProgress、Success、Cancelled、WaitingForEvents走各自分支Error分支优先取最后根交换root exchange的FinishedAIAgentOutput::Error其次取conversation.status_error()兜底取最后一个交换的终结状态。APP-4459 的增量是当没有已完成的根交换即失败发生在任何交换完成之前且conversation.status()为ConversationStatus::Error时直接把conversation.status_error_message()转换为AmbientConversationStatus::Error并规定错误载体为RenderableAIError::Otherwill_attempt_resume: falsewaiting_for_network: false。这确保了任务前失败任务尚未建立、没有交换可读也能被墓碑正确识别为错误状态而不是因为找不到根交换而丢失错误信息。五、ConversationEndedTombstoneView的错误数据来源5.1 展示数据结构墓碑的核心数据结构为TombstoneDisplayDataapp/src/terminal/view/shared_session/conversation_ended_tombstone_view.rs包含标题、错误标记、错误消息、是否为快照、来源、Skill 名、运行时长、积分、工作目录与 Artifact 列表。from_conversation从会话派生初始数据let conversation_status conversation_output_status_from_conversation(conversation); let is_error matches!( conversation_status, Some(AmbientConversationStatus::Error { .. }) ); let error_message conversation_status .as_ref() .and_then(|status| match status { AmbientConversationStatus::Error { error } Some(error.to_string()), _ None, });改造后is_error的判定扩展为conversation.status().is_error()或会话输出状态本身带错误两者任一成立即视为错误展示数据。5.2 任务前失败Pre-task Failure的特殊呈现在ConversationEndedTombstoneView::new中新增如下判定if display_data.is_error task_id.is_none() !display_data.conversation_is_transcript { display_data.title Some(Cloud agent failed to start.to_string()); display_data.credits None; }即当检测到错误会话 无任务 ID 无 transcript非快照查看模式时说明这是发生在任务建立之前的 Setup 失败此时标题固定为Cloud agent failed to start积分credits字段清空任务都没建立自然没有积分消耗可展示后续新增的hide_continue_actions会同时抑制 Continue locally 与 Continue in cloud 两类按钮——对一个从未启动的任务提供继续操作没有意义。5.3 异步任务数据丰富Task Enrichment墓碑在创建时会根据task_id异步拉取AmbientAgentTaskai_client.get_ambient_agent_task通过enrich_from_task丰富展示数据app/src/terminal/view/shared_session/conversation_ended_tombstone_view.rs无会话标题时使用任务标题填充来源Source与 Skill/配置名任务失败状态task.state.is_failure_like()会用task.status_message.message覆盖错误消息——这正是任务支撑失败优先于会话错误的实现用任务的运行时长、完整积分成本inference compute覆盖会话侧数据任务非空 Artifact 列表plans、PRs、files、screenshots覆盖会话侧 Artifact。改造保持该异步丰富链路不变并让任务失败元数据优先于会话错误成为明确规则。5.4 环境设置失败抑制 Continue 操作当任务丰富发现失败状态且TaskStatusMessage.error_code environment_setup_failed时同样隐藏 Continue 操作。原因环境设置失败意味着 Agent 从未真正进入可运行环境继续执行无从谈起。六、TaskStatusMessage的错误码扩展TaskStatusMessage位于 app/src/ai/ambient_agents/task.rs#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct TaskStatusMessage { pub message: String, #[serde(default, alias errorCode)] pub error_code: OptionTaskStatusErrorCode, /// Deadline of an open post-failure debug window (REMOTE-2208/REMOTE-2661)... #[serde(default)] pub session_debug_until: OptionDateTimeUtc, ... }要点error_code为可选字段#[serde(default)]保证服务端未下发该字段时反序列化为None不破坏旧数据结构兼容性alias errorCode让 Rust 侧字段名error_code能与服务端 JSON 的errorCode正确互转辅助方法is_environment_setup_failure()TaskStatusMessage与TaskStatusErrorCode两层均有用于墓碑展示决策识别环境设置失败类错误码从而决定隐藏 Continue 操作。错误码语义environment_setup_failed专门标记设置命令失败类错误这类失败不应提供继续操作continue actions。七、状态栏的减法移除通用失败分支BlocklistAIStatusBar::render_cloud_mode_setup_terminal_messageapp/src/ai/blocklist/block/status_bar.rs在 Setup-v2 下渲染云模式设置终结消息包含三个分支GitHub 鉴权分支github_auth_url()存在时渲染警示图标 错误消息 Authenticate GitHub 超链接 ——保留不变取消分支is_cancelled()渲染 Cloud agent run cancelled ——保留不变通用失败分支ambient_agent_model.error_message()渲染红色纯文本消息栏 ——在 Setup-v2 下移除或门控。改造后Setup-v2 的失败不再走通用失败消息栏因为错误已经由墓碑视图承载而 GitHub 鉴权与取消这两类会话并未终结的状态仍需要轻量消息栏故原样保留。Setup-v1 不受影响继续使用旧的失败 UI。八、测试与验证计划APP-4459 规划了针对性的 Rust 覆盖测试每一项都直接对应前述行为测试目标验证点Setup-v2Failed事件处理插入恰好一个墓碑并移除排队的 prompt block输入隐藏联动失败墓碑插入后TerminalView::is_input_box_visible返回false重复Failed事件仍只保留一个墓碑富内容视图任务前失败墓碑标题为Cloud agent failed to start隐藏积分与 Continue 操作任务支撑失败墓碑渲染AmbientAgentTask.status_message.message作为错误消息环境设置失败通过TaskStatusMessage.error_code识别并隐藏 Continue 操作状态栏回归Setup-v2 下状态栏不再渲染通用失败消息分支测试辅助入口已在ConversationEndedTombstoneView中提供#[cfg(test)]的title_for_test、error_message_for_test、credits_for_test、has_continue_locally_button_for_test、has_continue_in_cloud_button_for_test见 conversation_ended_tombstone_view.rs方便测试直接断言标题、错误消息、积分与按钮可见性。九、总结APP-4459 将 Cloud Mode Setup-v2 的启动失败呈现从Agent 消息栏红色错误条整体迁移到会话终结墓碑视图形成一条完整的失败语义链handle_spawn_error记录Status::Failed并发出Failed事件handle_ambient_agent_event把错误写入会话状态并在 Setup-v2 下插入墓碑防重复墓碑从会话状态 /AmbientAgentTask双来源汇总错误数据任务优先TaskStatusMessage.error_code environment_setup_failed或任务前失败时抑制 Continue 操作状态栏在 Setup-v2 下退役通用失败分支仅保留鉴权与取消分支。该方案复用了既有墓碑的输入隐藏联动、元数据展示与 Artifact 交互让失败获得与正常会话终结同等的结构化呈现同时通过错误码机制精确区分环境设置失败与普通任务失败避免对失败任务提供无效的继续操作。赞分享桌面应用开发者工具人工智能AI 应用AI Agent代码智能体【免费下载链接】warpWarp is an agentic development environment, born out of the terminal.项目地址https://gitcode.com/GitHub_Trending/wa/warp点击查看免费下载相关推荐RocksDB 范围墓碑转换Range Tombstone Conversion扫描路径上的墓碑合并优化RocksDB 范围墓碑转换Range Tombstone Conversion扫描路径上的墓碑合并优化 本文基于 RocksDB 官方技术博客 docs数据库KV存储嵌入式数据库存储Elsa Workflows 中 HTTP 上下文丢失的错误消息改进从静默挂起到快速失败Elsa Workflows 中 HTTP 上下文丢失的错误消息改进从静默挂起到快速失败 当一条由 HTTP 端点发起的工作流在挂起后被转移到不同执行上下文后端工作流自动化流程编排低代码Warp 云端 Agent 会话结束态行为基于 Harness 与对话编辑权限的 Tombstone / 续聊设计APP-4483Warp 云端 Agent 会话结束态行为基于 Harness 与对话编辑权限的 Tombstone / 续聊设计APP 4483 本指南以仓库内 spe桌面应用开发者工具人工智能AI 应用AI Agent代码智能体上一篇eslint-plugin-unicorn 的 prefer-class-fields 规则用类字段声明取代构造函数中的 this 赋值下一篇League Akari 使用清单3 分钟装好的英雄联盟免费助手把每局准备时间压进 2 秒创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考