Warp 桌面端 Orchestration 自定义 Worker Host 选择器(Host Picker)实现解析
桌面应用开发者工具人工智能AI 应用AI Agent代码智能体【免费下载链接】warpWarp is an agentic development environment, born out of the terminal.项目地址https://gitcode.com/GitHub_Trending/wa/warp点击查看免费下载导读Warp 的编排Orchestration能力允许用户从终端发起一次多智能体Agent协同任务将子 Agent 派发到云端执行。在早期版本中这些 Cloud Child Agent 的“执行主机”worker host被硬编码为默认的 Warp 集群warp使用自建 Workerself-hosted worker的团队无法从桌面客户端选择执行位置。本文基于仓库中 specs/QUALITY-701/PRODUCT.md 与配套技术设计 specs/QUALITY-701/TECH.md完整拆解 QUALITY-701“自定义 Host 选择器”的产品行为、交互细节与源码实现读完你将掌握该组件的两种渲染模式列表模式 / 自定义模式、持久化与最近使用recency策略、工作区默认主机的解析规则以及它与既有编排 Picker 管线OrchestrationPickerHandles的协作方式。背景编排 UI 中缺失的“最后一公里”编排 UIOrchestrate 确认卡片与 Plan 卡片上的 Orchestration 区块原本就有一行 Picker——模型model、harness、环境environment——用于驱动子 Agent 派发。真正派发时RunAgents请求携带的worker_host字段却始终是写死的warp路由到默认 Warp 集群。这带来两个问题运行自建 Worker 的团队无法从桌面客户端指定执行主机只能回到 Oz Web 应用其HostSelector是当时唯一的入口桌面客户端与 Web 端能力不一致缺少“选择执行位置”这一关键编排自由度。有趣的是worker_host字段在数据层早已贯通它存在于OrchestrationEditState与RunAgentsExecutionMode::Remote上缺少的只是一个让用户修改它的 UI 控件。QUALITY-701 补上的正是这一环并刻意复用了编排 Picker 既有的一套外观管线picker_styles()、Dropdown视图而不是另起炉灶。组件总览一个 View、两种模式QUALITY-701 的实现核心是一个非泛型视图HostPicker位于 app/src/ai/blocklist/inline_action/host_picker.rs。它内部维护一个状态机在两种渲染模式之间切换模式渲染内容触发方式代表行为列表模式List mode复用DropdownInternalAction样式与其余编排 Picker 完全一致默认状态展示默认 /warp/ 最近自定义 / “Custom host…”自定义模式Custom mode内联单行EditorView 右侧小型取消按钮点击 “Custom host…” 或外部注入未知 slug输入任意 slugEnter / 失焦提交Escape / 取消还原两种模式共享同一个“当前选择”current_slug模式切换不丢失状态进入自定义模式时会用slug_before_edit记录快照取消时可精确回滚。该视图对外只暴露两个公共事件HostPickerEvent::HostChanged { slug }——任何一次选择变更点选已知项或提交自定义值都会发出HostPickerEvent::Closed——菜单关闭或编辑器失焦时发出供父卡片把焦点交还给自己的输入框。对应的公共 API 则包括set_options(default, recent, connected, ctx)重建菜单行、set_selected(slug, ctx)设置显示值未知 slug 自动切入自定义模式、set_use_overlay_layer(...)菜单浮层层级与set_menu_position(...)菜单锚点/朝向。列表模式菜单项的排序、徽章与去重列表模式的菜单内容由纯函数build_menu_items生成位于 host_picker.rs它接受default_host、recent_host与connected_hosts三路输入按以下顺序产出菜单行工作区默认 slug团队配置了defaultHostSlug时出现带“Default”徽章且固定在首位warpWarp 默认集群无条件始终存在当前已连接的 Worker slug带“Connected”徽章按字母序、去重后插入最近使用的自定义 slug无徽章渲染为纯文本若该 slug 当前不在连接集合中则额外标注“Disconnected”使其可选中但状态明确“Custom host…”条目固定最后选中后切换进入自定义模式。去重规则产品行为 5有两层保障。首先ConnectedSelfHostedWorkersModel::worker_hosts_excluding在数据来源侧就排除了warp与默认 slug见 app/src/ai/connected_self_hosted_workers.rs其次build_menu_items内部用known_slugs列表做大小写不敏感eq_ignore_ascii_case的二次去重确保“最近自定义 默认”或“最近自定义 warp”时不产生重复行。build_host_snapshotapp/src/ai/orchestration/snapshots.rs中的OptionBadge::Default / Connected / Recent徽章体系与上述菜单构建逻辑一一对应而populate_host_pickerorchestration_controls.rs正是读取该快照后把三类行分别灌入HostPicker::set_options。自定义模式内联编辑器的完整交互语义点击 “Custom host…” 后Picker 顶栏被替换为一个内联文本编辑器其交互语义在产品文档中被拆成 5 条可测试的规则行为 8–12源码中分别对应预填充编辑器打开时以当前 slug 预填若当前就是warp则预填为空见enter_custom_mode_with_slughost_picker.rs提交按 Enter 或编辑器失焦EditorEvent::Blurred触发commit_custom提交前手动trim()去除首尾空白handle_editor_event空输入 还原commit_custom对空 buffer 直接走cancel_custom等价于“不做任何修改”行为 10大小写不敏感的 warp输入warp/WARP并提交时不把它持久化为自定义值而是折叠回标准warp选中态行为 11——这避免了“current_slug是warp的大小写变体、与任何菜单标签都不匹配”的不对称情形取消Escape 或点击右侧的 ✕ 取消按钮render_cancel_button一个 16×16 的 X 图标Hoverable按钮触发cancel_custom依据slug_before_edit快照回滚到进入编辑前的选中值行为 9。提交一个非空、非warp的 slug 时还会发生两件事该 slug 被提升进recent_host字段!self.is_known_option(raw)时才提升避免与默认/已连接行重复并在下一次打开菜单时以“最近使用”行出现同时通过HostChanged事件交给父层持久化行为 12详见下一节。值得单独强调的两处实现细节垂直居中行为 13自定义模式的外壳用Flex::columnMainAxisAlignment::Center包裹编辑器并在最外层套上与标准Dropdown相同的上下DROPDOWN_PADDING外边距使编辑框文字垂直居中、且整盒与同一行其他 Picker 保持相同 y 偏移render_custom_modeClose 事件抑制进入自定义模式期间内层DropdownEvent::Close会被is_custom_mode检查吞掉。若不抑制父卡片会在菜单关闭时抢回焦点把刚聚焦的编辑器 blur触发 commit-on-blur 立即退回列表模式——使 “Custom host…” 看起来像个无效操作。这是该功能在 UX 层面最容易翻车的一处防御见 host_picker.rs 中 Dropdown 订阅逻辑。选择模型与工作区默认主机解析产品文档的“Selection model”行为 14–16与“Persistence and recency”行为 17–18在源码层被提炼为三个纯函数app/src/ai/orchestration/providers.rsresolve_default_host_slug(scope, ctx) - OptionString——返回团队配置的工作区默认主机 slug优先读取开发者专用的WARP_CLOUD_MODE_DEFAULT_HOST环境变量本地测试覆盖否则回退到UserWorkspaces::default_host_slug(scope)并过滤空值resolve_recent_host_slug(scope, ctx) - OptionString——从CloudAgentSettings.last_selected_host读取用户最近一次自定义选择但对warp大小写不敏感与当前团队默认值做双重排除避免菜单出现重复行行为 18persist_host_selection(worker_host, ctx)——把 slug 写回CloudAgentSettings.last_selected_host跳过空值与warp行为 17。这条规则保证了“最近使用”行永远只收录真正有意义的自定义 slug。三条产品行为在此得到印证行为 14永不空选normalize_slug对输入trim()后空串一律回退为warphost_snapshot中current的解析同样在空worker_host时落到warp。两条路径共同保证 Picker 恒有非空选择行为 15未知 slug 进入自定义模式HostPicker::set_selected先对 slug 做归一化再调用is_known_option对warp、默认、最近、已连接四类做大小写不敏感比对不匹配即enter_custom_mode_with_slug预填该 slug 而非显示一条“幽灵菜单项”行为 16默认预选当工作区配置了默认主机且用户尚无显式选择last_selected_host为空时HostSelector::set_default_hostapp/src/terminal/view/ambient_agent/host_selector.rs与编排侧的populate_host_picker都优先预选默认值而非warp反之若用户已有持久化选择则尊重用户选择、仅把默认值作为菜单项提供。clear_default_host的注释还揭示了一个细节窗口切换到“未配置默认主机”的团队时同样以用户保存的选择优先避免上一位团队的默认 Worker 被错误沿用。双表面接入确认卡片与 Plan 卡片Picker 需要同时出现在两处 UI且两处的菜单朝向策略不同行为 20Orchestrate 确认卡片app/src/ai/blocklist/inline_action/run_agents_card_view.rs在ensure_pickers中为新的host_picker槽构建视图调用picker.set_menu_position(PositionedElementAnchor::TopLeft, ChildAnchor::BottomLeft)让菜单向上翻开与同卡片其他下拉保持一致避免与下方的 Environment / Base model 行视觉碰撞订阅HostChanged后重新派发既有的RunAgentsCardViewAction::WorkerHostChangedPlan 卡片app/src/ai/document/orchestration_config_block.rs调用picker.set_use_overlay_layer(true)让菜单绘制在**覆盖层overlay layer**之上、盖过同行的兄弟 PickerWorkerHostChanged除更新编辑态与持久化外还会调用apply_field_change把新值写进该 Plan 存储的OrchestrationConfig快照行为 19 的“plan card 额外持久化”。两个WorkerHostChanged处理器的逻辑高度一致见 run_agents_card_view.rs 与 orchestration_config_block.rs先set_worker_host写入OrchestrationConfigState再persist_host_selection写入最近使用设置因此“任何以主机变更收尾的路径都会持久化 slug”。共享 Picker 管线OrchestrationPickerHandles的扩展为了让两个卡片共享同一套初始化与同步逻辑orchestration_controls.rs对既有管线做了四点增量改造OrchestrationPickerHandles新增host_picker: OptionViewHandleHostPicker槽位新函数populate_host_picker(picker, initial_host, ctx)——读取host_snapshot含默认/最近/已连接三类行调用picker.set_options后按初始 host 调用picker.set_selected空输入自动回退warp两个卡片在ensure_pickers期间共用它完成播种sync_picker_selections被扩展为在编辑态每次变化时调用picker.set_selected同步当前worker_host——这同时覆盖了初始填充与“其他 Picker 引发的级联变化”例如模式切换把 host 重置回warp恢复 Remote 配置且 host 为空时两个卡片都优先预填工作区默认值而非裸warp与 Oz Web 应用保持一致。由于worker_host字段在OrchestrationEditState与RunAgentsExecutionMode::Remote上本就存在本次改造无需触碰派发dispatch、服务端序列化server marshalling与 auto-launch 匹配逻辑——之前写死的warp与用户选择的任意 slug 走的是同一条代码路径见 TECH.md 第 5 节“No other call sites”。测试与验证策略纯逻辑与视图行为采用了不同的验证方式单元测试host_picker_tests.rs直接测试无视图上下文的纯函数覆盖产品行为 4/5/6/8/11/14/15/16/18包括无默认、无最近时菜单仅warp “Custom host…”两项默认存在时置顶且带徽章最近存在时排在warp之后、渲染为纯文本最近 默认、最近 warp时的去重warp行派发SelectKnown(warp)、自定义行派发EnterCustomModemenu_label_for对默认 slug 打 “Default” 徽章、对未知值返回纯文本normalize_slug的 trim 与空输入回退warp。菜单排序与去重的纯逻辑在快照层还有独立测试佐证host_snapshot_orders_default_warp_connected_recent与host_snapshot_dedupes_connected_and_recent_against_known_rowsapp/src/ai/orchestration/snapshots_tests.rs。手动冒烟测试覆盖视图驱动行为TECH.md 附有逐条清单自定义模式提交/失焦/焦点归还、与兄弟 Picker 的图层交互、端到端验证等。其中最关键的一条是行为 19 的端到端验证选择非warpslug 后派发 AgentWorker 日志中出现task_claimed worker_id:local-dev即证明自定义 slug 正确路由到了自建 Worker。小结QUALITY-701 是一个典型的“补齐数据链路最后一环”的 UI 功能数据层worker_host早已贯通工作量集中在一个双模式视图与两个卡片的薄接线thin wiring上。其工程价值在于三点产品行为被精确拆解为可单元测试的纯函数外观与交互复用既有 Picker 管线同一套picker_styles()常量、Dropdown与 overlay 机制而零散改去重、默认预选、recency 与“warp 永不持久化”等边界规则被浓缩为三个纯函数行为可预测且易测。对于希望在自建 Worker 环境下使用 Warp 编排能力的团队这一功能补全了“在哪里执行”这一关键选择权对于开发者而言host_picker.rs 与其配套测试则是一份紧凑的“模式化 Picker 组件”参考实现。赞分享桌面应用开发者工具人工智能AI 应用AI Agent代码智能体【免费下载链接】warpWarp is an agentic development environment, born out of the terminal.项目地址https://gitcode.com/GitHub_Trending/wa/warp点击查看免费下载相关推荐Podman --add-host 选项全解析自定义容器 /etc/hosts 映射与 host-gateway 网关地址Podman add host 选项全解析自定义容器 /etc/hosts 映射与 host gateway 网关地址 add host 是 Podman 中容器运行时云原生CLIAndroidHttpCapture Host配置完全指南自定义域名解析实战AndroidHttpCapture Host配置完全指南自定义域名解析实战 AndroidHttpCapture是一款功能强大的Android手机抓包软件网络开发工具Apache Maka 桌面端 Task Entry / Workspace 架构解析新任务目标选择与 Workspace Picker 的前端实现Apache Maka 桌面端 Task Entry / Workspace 架构解析新任务目标选择与 Workspace Picker 的前端实现 导读 T人工智能AI Agent自主智能体工具调用交互助手AI 评测创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考