☰
Warp 完成通知中的 Artifact 行:从事件溯源到交互式 Chip 的完整设计与实现
2026/10/2 13:48:53 网站建设 项目流程
  • 桌面应用
  • 开发者工具
  • 人工智能
  • AI 应用
  • AI Agent
  • 代码智能体

【免费下载链接】warp

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

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

导读

本指南以 Warp 开源仓库中的产品与技术规格(specs/APP-3630/PRODUCT.md 与 specs/APP-3630/TECH.md)为核心,系统讲解 Warp 通知系统的一项关键增强:当 Agent 在对话中产出 Plan、Pull Request、截图等产物(Artifact)时,对话一旦进入终态(成功 / 取消 / 出错),完成通知(Toast 弹窗与通知信箱 Mailbox)都会在标准内容下方渲染一行可交互的 Artifact Chip,点击通知本体即可跳转到对应对话。读完本文,你将理解该功能的完整数据流——从UpdatedConversationArtifacts事件的载体改造,到AgentNotificationsModel的跨轮累积策略,再到NotificationItem数据结构与渲染层的交互组件接入,并掌握每一步对应的仓库源码位置,可直接对照当前实现进行二次开发。

一、问题背景:Agent 产物为何“静默”

Warp 中,Agent 在对话过程中会持续创建各种产物(Artifact),典型包括:

  • Plan(行动计划,可同步到 Warp Drive 的 notebook)
  • Pull Request(已创建的 PR,携带 URL 与分支名)
  • Screenshot(截图)
  • File(生成的文件)
  • ExternalReference(外部引用)

在增强之前,用户对这些产物的感知存在明显缺口:只有对话状态发生变更(完成、阻塞、出错)时系统才会触发通知,而产物本身并不会触发任何通知。如果用户没有主动进入对话查看,就完全无从得知 Agent 已经生成了计划、提了 PR 或截了图——产物在通知层面是“静默”的。

仓库中的源码可以印证这一现状的“历史边界”:

  • 通知数据结构 NotificationItem 原本只承载title、message、category、agent、origin、is_read、created_at、terminal_view_id,不含任何产物数据;
  • 通知创建模型 AgentNotificationsModel 监听的是UpdatedConversationStatus事件,通过handle_history_event_for_mailbox生成通知,并未监听UpdatedConversationArtifacts。

规格书(PRODUCT.md)据此给出明确判断:现有通知只在状态变化时触发,产物的产生对用户完全不可见。

二、期望行为与设计约束(Scope 总览)

规格书为本次增强划定了清晰的边界,这是理解后续实现的关键:

维度约束
触发条件复用现有完成通知(UpdatedConversationStatus到达终态),不新增独立产物通知
产物范围自上一次终态通知以来新增的全部产物,即跨当前响应的所有轮次累积
交互性Artifact Chip 可交互,使用与管理视图(agent_management 视图)完全相同的按钮
点击行为点击通知本体导航到对应对话
展示面Toast 弹窗 + 通知信箱(Mailbox)双端一致
特性开关由hoa_notifications(通知系统现有开关)控制

两个值得注意的设计取舍:

  1. 不新增通知类型。产物信息作为完成通知的“附加行”出现,避免通知轰炸——如果每个产物都单独发一条通知,一轮产生 5 个 PR 就会出现 5 条通知;
  2. “终态才呈现”。产物在对话进行中会持续累积,只有到达终态(Success / Cancelled / Error)时才一次性呈现在完成通知里。

从源码看,hoa_notifications在仓库中体现为编译特性 + 运行时开关的组合:features.rs中 FeatureFlag::HOANotifications 在#[cfg(feature = "hoa_notifications")]下注册,模型层也通过FeatureFlag::HOANotifications.is_enabled()判断是否走信箱通知路径(见 agent_management_model.rs)。

三、现状盘点:四个关键代码位置

TECH.md 首先对现状做了精确盘点,四个位置分别对应“数据、创建、事件、渲染”四个环节:

3.1 通知数据:NotificationItem

NotificationItem位于 app/src/ai/agent_management/notifications/item.rs。规格撰写时它没有产物字段;当前仓库中该结构已经扩展出artifacts: Vec<Artifact>与branch: Option<String>两个字段(后者用于通知的“富布局”分支头行渲染),NotificationItem::new也相应接收artifacts与branch参数。这印证了本功能在当前分支上已落地,后续源码阅读均以“已实现版本”为准。

3.2 通知创建:AgentNotificationsModel

单例模型 AgentNotificationsModel 负责两类来源的通知:

  • Warp Agent 对话:订阅BlocklistAIHistoryModel,在handle_history_event中响应UpdatedConversationStatus;
  • CLI Agent 会话(Codex 等):按终端视图(CLISession)跟踪。

它只监听状态事件、不监听产物事件,这正是本功能需要打通的“缺口”。

3.3 产物事件:UpdatedConversationArtifacts

事件定义在 app/src/ai/blocklist/history_model.rs。规格撰写时该事件只携带terminal_surface_id与conversation_id,不含产物本体;当前仓库中已增加artifact: Artifact字段。

事件的发射点有两处(均在 app/src/ai/agent/conversation.rs):

  • AIConversation::add_artifact:向对话追加产物并持久化,随后发射事件(先 clone 再 push,保证事件中携带的是独立的产物副本);
  • update_plan_notebook_uid:当 Plan 产物同步到 Warp Drive、获得notebook_uid后更新并发射事件。

此外,从 history_model.rs 可以看到事件的上游来源:远端消息流中的artifact_event(PR / Screenshot / File 的Created事件,以及fork_artifacts)都会被转换为Artifact并调用add_artifact。

3.4 渲染:render_notification_item_content

渲染函数 render_notification_item_content 位于 item_rendering.rs,负责渲染头像 + 标题 + 消息。规格撰写时它只接收&NotificationItem与&Appearance,没有视图上下文,因此无法渲染任何交互组件。

3.5 交互组件范式:ArtifactButtonsRow

管理视图(agent_management/view.rs)中已经存在成熟的产物按钮行模式:创建ViewHandle<ArtifactButtonsRow>、订阅事件、把句柄存进CardState。本功能要做的就是把这套模式复用到通知场景。

交互组件的实现位于 app/src/ai/artifacts/buttons.rs:

  • ArtifactButtonsRow内部是一组ViewHandle<ActionButton>,渲染产物对应的按钮(计划、分支、PR);
  • 事件枚举ArtifactButtonsRowEvent定义了OpenPlan(携带notebook_uid)、CopyBranch(携带分支名)、OpenPullRequest(携带 URL)等动作;
  • 产物类型枚举Artifact定义在 app/src/ai/artifacts/mod.rs:PLAN、PULL_REQUEST、EXTERNAL_REFERENCE、SCREENSHOT、FILE五种变体,带serde(tag = "artifact_type")的标签式序列化,并通过#[serde(rename = "...")]与远端协议对齐。

四、实现方案:五步改造链路

TECH.md 将实现拆解为 5 步,其内在依赖关系是:第 1 步必须先行(数据载体是前提),第 2-3 步与第 4-5 步可并行(详见“并行性”一节)。下面按数据流顺序展开。

第 1 步:让事件“携带”产物本体

在UpdatedConversationArtifacts中新增artifact: Artifact字段,并在两个发射点克隆产物:

  • add_artifact:在 push 进self.artifacts之前 clone(当前实现见 conversation.rs);
  • update_plan_notebook_uid:在修改产物之后 clone(当前实现见 conversation.rs)。

这一步的意义:事件从“信号”升级为“信号 + 载荷”。下游订阅方(通知模型)不再需要反向查询对话状态来推断产物,而是直接拿到产物副本,解耦了数据获取逻辑。

第 2 步:在 AgentNotificationsModel 中跨轮累积产物

在AgentNotificationsModel中新增:

pending_artifacts: HashMap<AIConversationId, Vec<Artifact>>

累积规则是整个功能的行为核心,规格给出了明确的状态机语义:

事件行为
UpdatedConversationArtifacts将产物 append 到pending_artifacts[conversation_id]
InProgress不清空pending_artifacts—— 产物跨轮累积
终态(Success / Cancelled / Error)drainpending_artifacts[conversation_id],传给add_notification
对话删除 / 移除清理对应pending_artifacts条目
CLI Agent 通知传入空 vec

当前仓库实现完全遵循了该设计:

  • 模型字段即 pending_artifacts;
  • 在handle_history_event_for_mailbox中,ConversationStatus::Success、Cancelled、Error三个分支都先调用self.flush_pending_artifacts(conversation_id)取出累积产物,再传给add_notification(见 agent_management_model.rs);
  • Blocked(Request类别)不进入终态,因此不 flush、不携带产物。

这里有一个值得强调的细节:“InProgress 不清空”保证了多轮产物的完整累积。假设 Agent 先给出 Plan,又等待用户确认后创建 PR,最后才完成——两条产物都会出现在最终的完成通知里,而不是只有最后一轮的 PR。

第 3 步:给 NotificationItem 增加 artifacts 字段

为NotificationItem增加artifacts: Vec<Artifact>,并贯通NotificationItem::new与add_notification的整个调用链。

仓库当前实现中,该字段及其构造参数已经存在(见 item.rs 与 item.rs),通知项还额外携带了branch: Option<String>,用于触发“富布局”渲染。

第 4 步:在 Toast 与 Mailbox 中持有 ArtifactButtonsRow 视图

NotificationToastItem与NotificationMailboxView各自为每条通知存储一个Option<ViewHandle<ArtifactButtonsRow>>:

  • 创建时机:通知新增时创建视图;
  • 订阅:订阅ArtifactButtonsRowEvent,处理OpenPlan/CopyBranch/OpenPullRequest等动作;
  • 行为对齐:动作处理逻辑与agent_management/view.rs(管理视图)中的ArtifactButtonsRowEvent处理保持一致。

仓库中该环节的封装位于 item_rendering.rs:create_notification_artifact_buttons_view在产物为空时返回None,否则以NotificationArtifactButtonTheme创建ArtifactButtonsRow;事件处理由 handle_notification_artifact_buttons_event 统一接管(打开 Plan、跳转 PR、复制分支等动作均伴随遥测事件上报)。

从文件分布看,两个承载视图分别位于:

  • notifications/toast_stack.rs(Toast 弹窗堆栈)
  • notifications/view.rs(Mailbox 视图)

第 5 步:把产物视图接入渲染

为render_notification_item_content增加Option<&ViewHandle<ArtifactButtonsRow>>参数,当存在时在消息文本下方渲染ChildView(子视图),并更新 Toast 与 Mailbox 两处调用点。

当前仓库中该函数签名已经是render_notification_item_content(item, artifact_buttons, context, message_expanded, on_expand_click, extra_content)(见 item_rendering.rs),内部按item.branch是否为空分派两种布局:

  • 富布局render_rich_text_column:分支头行 + 截断标题 + 截断消息 + 产物按钮(item_rendering.rs);
  • 简单布局render_simple_text_column:标题 + 时间戳行 + 消息 + 产物按钮(item_rendering.rs)。

两种布局最终都通过append_trailing_content把产物按钮行追加到文本列之后(item_rendering.rs),从而保证 Toast 与 Mailbox 的视觉一致性。

五、并行性与实施顺序

规格在最后明确了工程的依赖图:

第 1 步(事件携带产物) │ ├── 第 2 步(模型累积)──┐ └── 第 3 步(Item 字段)──┼── 可并行 │ ┌── 第 4 步(视图持有)──┤ └── 第 5 步(渲染接入)──┘

即:第 1 步是硬前置,因为它定义了产物数据到达通知系统的通道;第 2-3 步(模型层累积 + 数据结构)与第 4-5 步(视图层持有 + 渲染接入)在各自内部可以并行推进,因为视图层的ViewHandle只是“选项句柄”,即便通知项尚无产物,Option<ViewHandle>取None时渲染层也能自然回退到无产物布局,不会破坏编译与运行。

这种分层并行也体现在当前仓库的模块划分上:数据层(notifications/item.rs)、模型层(agent_management_model.rs)、渲染层(notifications/item_rendering.rs)、承载层(notifications/toast_stack.rs/notifications/view.rs)各司其职,彼此通过类型与句柄解耦。

六、端到端数据流小结

把上述五步串起来,一次完整的“产物通知”体验是这样的:

  1. Agent 在对话中创建产物(Plan / PR / 截图 / 文件),远端事件或本地逻辑触发AIConversation::add_artifact或update_plan_notebook_uid;
  2. 产物被 push 进对话状态,同时克隆后随UpdatedConversationArtifacts事件(现已携带artifact)广播出去;
  3. AgentNotificationsModel收到事件,将产物追加到pending_artifacts[conversation_id];InProgress状态不清空,产物跨轮累积;
  4. 对话到达终态,UpdatedConversationStatus触发完成通知路径,模型 drain 累积产物并写入NotificationItem.artifacts;
  5. Toast 与 Mailbox 收到通知项后,通过create_notification_artifact_buttons_view创建ArtifactButtonsRow并订阅其事件;
  6. render_notification_item_content在标准内容下方渲染产物按钮行;用户点击按钮可打开 Plan / 跳转 PR / 复制分支,点击通知本体则导航到对应对话。

七、延伸阅读:仓库中的配套实现

  • 产品规格:specs/APP-3630/PRODUCT.md
  • 技术规格:specs/APP-3630/TECH.md
  • 通知数据结构:app/src/ai/agent_management/notifications/item.rs
  • 通知创建模型:app/src/ai/agent_management/agent_management_model.rs
  • 通知渲染与按钮创建:app/src/ai/agent_management/notifications/item_rendering.rs
  • 产物类型定义:app/src/ai/artifacts/mod.rs
  • 产物按钮行组件:app/src/ai/artifacts/buttons.rs
  • 产物事件定义与发射:app/src/ai/blocklist/history_model.rs、app/src/ai/agent/conversation.rs
  • 特性开关注册:app/src/features.rs

如需验证行为逻辑,可进一步查阅agent_management_model_tests.rs中关于产物累积与终态 flush 的测试用例,它们与本功能的状态机语义一一对应。

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

【免费下载链接】warp

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

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

相关推荐

上一篇:AI Red Teaming 视角下的神经网络:掌握层、节点与激活函数以实施精准对抗测试
下一篇:MMDetection 训练实战指南:标准数据集与自定义数据集的完整训练流程

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

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

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

立即咨询