news 2026/10/3 8:35:53

Warp 云模式(Cloud Mode)Setup-v2 失败 Tombstone 化改造:从错误消息栏到会话终结墓碑视图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Warp 云模式(Cloud Mode)Setup-v2 失败 Tombstone 化改造:从错误消息栏到会话终结墓碑视图
  • 桌面应用
  • 开发者工具
  • 人工智能
  • AI 应用
  • AI Agent
  • 代码智能体

【免费下载链接】warp

Warp 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 设置流程 v2(Setup-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 处理链路是:

  1. AmbientAgentViewModel::handle_spawn_error将 ViewModel 状态置为Status::Failed { error_message },并发出AmbientAgentViewModelEvent::Failed,见 app/src/terminal/view/ambient_agent/model.rs。
  2. TerminalView::handle_ambient_agent_event收到Failed事件后,移除排队的 prompt block、更新活跃云会话状态、刷新详情面板并通知重绘,见 app/src/terminal/view/ambient_agent/view_impl.rs。
  3. 最终由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_tombstone(app/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::Other(will_attempt_resume: false、waiting_for_network: false)
ConversationEndedTombstoneViewapp/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 优先级最高):

  1. AmbientAgentTask.status_message.message—— 有任务支撑(task-backed)的失败,尤其是第三方 harness 运行时,本地AIConversation仅作为 UI 载体,任务消息才是事实来源;
  2. 会话状态错误(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决定使用何种 CTA(Continue in Cloud / Continue locally / 无 CTA),见 app/src/terminal/view/shared_session/view_impl.rs。

3.2 防重复插入

墓碑插入统一收敛在insert_conversation_ended_tombstone_with_cta:

if 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视为非终结状态,返回None;
  • Blocked、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::Other;
  • will_attempt_resume: false;
  • waiting_for_network: false。

这确保了"任务前失败"(任务尚未建立、没有交换可读)也能被墓碑正确识别为错误状态,而不是因为找不到根交换而丢失错误信息。

五、ConversationEndedTombstoneView的错误数据来源

5.1 展示数据结构

墓碑的核心数据结构为TombstoneDisplayData(app/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异步拉取AmbientAgentTask(ai_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: Option<TaskStatusErrorCode>, /// Deadline of an open post-failure debug window (REMOTE-2208/REMOTE-2661)... #[serde(default)] pub session_debug_until: Option<DateTime<Utc>>, ... }

要点:

  • 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_message(app/src/ai/blocklist/block/status_bar.rs)在 Setup-v2 下渲染"云模式设置终结消息",包含三个分支:

  1. GitHub 鉴权分支(github_auth_url()存在时):渲染警示图标 + 错误消息 + "Authenticate GitHub" 超链接 ——保留不变;
  2. 取消分支(is_cancelled()):渲染 "Cloud agent run cancelled" ——保留不变;
  3. 通用失败分支(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 消息栏红色错误条"整体迁移到"会话终结墓碑视图",形成一条完整的失败语义链:

  1. handle_spawn_error记录Status::Failed并发出Failed事件;
  2. handle_ambient_agent_event把错误写入会话状态,并在 Setup-v2 下插入墓碑(防重复);
  3. 墓碑从会话状态 /AmbientAgentTask双来源汇总错误数据(任务优先);
  4. TaskStatusMessage.error_code == environment_setup_failed或任务前失败时抑制 Continue 操作;
  5. 状态栏在 Setup-v2 下退役通用失败分支,仅保留鉴权与取消分支。

该方案复用了既有墓碑的输入隐藏联动、元数据展示与 Artifact 交互,让"失败"获得与"正常会话终结"同等的结构化呈现,同时通过错误码机制精确区分"环境设置失败"与普通任务失败,避免对失败任务提供无效的继续操作。

  • 桌面应用
  • 开发者工具
  • 人工智能
  • AI 应用
  • AI Agent
  • 代码智能体

【免费下载链接】warp

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

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

相关推荐

上一篇:eslint-plugin-unicorn 的 prefer-class-fields 规则:用类字段声明取代构造函数中的 `this` 赋值
下一篇:League Akari 使用清单:3 分钟装好的英雄联盟免费助手,把每局准备时间压进 2 秒

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 8:32:19

CogBench: A Large Language Model Benchmark for Multilingual Speech-Based Cognitive Impairment Ass...

主要内容 本文聚焦于基于语音的认知障碍自动评估,针对现有方法在跨语言和跨临床场景下泛化能力不足的问题,提出了首个用于评估大型语言模型(LLMs)在该任务中跨语言和跨站点泛化能力的基准CogBench。 研究使用统一的多模态流程,在涵盖英语和普通话的三个语音数据集(ADRe…

作者头像 李华
网站建设 2026/10/3 8:21:42

CMake get_property 命令完全指南:十种作用域属性读取与源码实现解析

构建工具开发工具CLI 【免费下载链接】CMake Mirror of CMake upstream repository 项目地址&#xff1a; https://gitcode.com/gh_mirrors/cm/CMake 点击查看 免费下载 get_property 是 CMake 中读取属性的通用入口命令&#xff0c;它从全局、目录、目标、源文件、测试、缓存…

作者头像 李华