ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Warp 自定义工具栏命令绑定 CLI Agent:从 Unknown 会话到完整 Agent 体验

Warp 自定义工具栏命令绑定 CLI Agent:从 Unknown 会话到完整 Agent 体验 桌面应用开发者工具人工智能AI 应用AI Agent代码智能体【免费下载链接】warpWarp is an agentic development environment, born out of the terminal.项目地址https://gitcode.com/GitHub_Trending/wa/warp点击查看免费下载自定义命令如公司内部脚本uber-cli、my-claude-wrapper在 Warp 中匹配工具栏规则后过去只能得到CLIAgent::Unknown会话缺失图标、品牌色、Rich Input 提交策略、技能与插件监听等专属体验。本篇文章基于 Warp 开源仓库中的 APP-4060 产品规格 与技术规格 TECH.md结合源码实现完整讲解「一条自定义工具栏命令绑定一个 CLI Agent」的配置方式、底层数据结构、检测链路与插件生命周期。读完后你将掌握如何在设置界面为自定义命令选择 Agent、其配置如何持久化与云同步、命令检测如何携带 Agent 信息以及自定义命令如何获得与原生检测 Agent 完全一致的体验。背景与问题自定义命令为何总是沦为 Unknown 会话Warp 会把长时间运行的命令超过LONG_RUNNING_COMMAND_DURATION_MS阈值后与具体 CLI Agent 关联从而在终端底部显示对应 Agent 的工具栏Toolbar。对于原生命令claude、codex、gemini等CLIAgent::detect 可以直接通过命令前缀识别。但现实中很多用户会通过包装脚本或别名调用 CLI Agent例如 Uber 团队使用的aifx agent run claude或者形如my-claude-wrapper的自定义别名。这类命令无法被前缀规则命中只能依靠用户在设置中添加正则模式Commands that enable the toolbar来启用工具栏。问题在于旧实现中正则匹配只返回一个布尔值命中的会话被无条件标记为CLIAgent::Unknown于是工具栏显示通用外观没有 Agent 的图标与品牌色会话被标记为CLIAgent::Unknown导致不会创建插件监听器没有富状态、Rich Input 的自动显隐Rich Input 提交策略退化为默认的Inline而不是该 Agent 最合适的策略斜杠菜单中缺少该 Agent 专属的 skill provider通知消息缺少 Agent 的显示名与图标。产品规格PRODUCT.md的核心目标就是给「正则模式 → CLI Agent」之间架起一座桥让用户显式告诉 Warp 某个自定义模式代表哪个 Agent。目标与非目标目标允许用户为每条自定义工具栏命令模式指定一个具体 CLI Agent模式命中后会话表现与原生检测到的 Agent 完全一致图标、品牌、插件监听资格、Rich Input 策略、技能、通知保持aifx agent run claude对 Uber 团队成员的既有 Claude 检测逻辑不变。非目标不改变已知 Agent 的自动检测逻辑不支持一个模式绑定多个 Agent一个模式 一个 Agent不新增新的 CLI Agent 类型不改变自定义命令的插件安装/更新流程现有 install chip 逻辑已按 Agent 做插件检查。设置界面为每条命令选择 Agent行布局设置列表中每条命令新增一个右侧下拉框整体布局为[命令正则文本] [Agent Dropdown ▼] [× 移除]命令文本左对齐且可收缩等宽字体下拉框固定宽度并与命令文本同组靠左移除按钮右对齐。折叠状态下下拉框顶部栏直接显示已选 Agent 的名称。下拉项下拉菜单列出所有已知 CLI Agent每一项展示Agent 图标来自CLIAgent::icon()Agent 显示名来自CLIAgent::display_name()如 Claude Code、Gemini、Codex首个默认项 CLI Agent无图标新添加的模式默认选中它。CLIAgent::Unknown不会作为可选项目出现在下拉中——它被 CLI Agent 这个默认项所代表。产品规格中默认项文案为 CLI Agent而当前仓库落地实现cli_agents_page.rs将其命名为 Other并把菜单头部文案覆盖为 Select coding agent语义一致。添加 / 移除 / 修改添加通过文本输入框提交新命令后以默认 CLI Agent空值加入列表用户随后可用下拉框修改移除删除命令时其 Agent 映射一并从底层设置中清理同一 HashMap 条目内模式与 Agent 共存天然无孤儿数据修改选择下拉中的某个 Agent 会立即持久化并通过与其他 AI 设置相同的机制同步到云端。从当前源码看该设置项定义在 app/src/settings/ai.rs 的cli_agent_footer_enabled_commandsTOML 路径agents.third_party.cli_agent_toolbar_enabled_commands其sync_to_cloud为Globally(RespectUserSyncSetting::Yes)即遵循用户云同步开关进行全局同步。下拉框的源码级实现设置页的每个下拉框由create_cli_agent_dropdowns创建cli_agents_page.rs核心配置包括set_top_bar_max_width(160.)紧凑的顶部栏宽度set_menu_width(180.)容纳「图标 名称」的菜单宽度set_main_axis_size(MainAxisSize::Min)按内容宽度自适应菜单项遍历enum_iterator::all::CLIAgent()跳过Unknown为每个 Agent 构造MenuItemFields::new(agent.display_name()).with_icon(agent.icon())选中后派发SetCLIAgentForCommand { pattern, agent }动作通过set_selected_by_name依据当前保存值空值显示为 Other恢复选中状态。下拉组件本身是通用的Dropdownview_components/dropdown.rs菜单项支持with_iconmenu.rs。底层数据结构ToolbarCommandMap 与旧数据迁移产品与技术规格要求把设置类型从VecString升级为「模式 → Agent」的映射结构。当前仓库以ToolbarCommandMap实现app/src/settings/ai.rs/// 键为命令正则模式保序值为序列化的 CLIAgent 名如 Claude。 /// 空字符串值表示 CLI Agent即 CLIAgent::Unknown。 pub struct ToolbarCommandMap(IndexMapString, String);两个关键设计1. 用IndexMap而非HashMap保序。技术规格的风险章节明确提到HashMap不保证迭代顺序、可能导致设置列表乱序落地实现选择了IndexMap使设置界面列表顺序确定按插入序。2. 向后兼容的反序列化。旧的设置格式是字符串数组[pattern1, pattern2]新格式是映射{pattern1: Claude, pattern2: }。ToolbarCommandMap通过#[serde(untagged)]枚举同时兼容两种格式#[derive(Deserialize)] #[serde(untagged)] enum MapOrVec { Map(IndexMapString, String), Vec(VecString), } // Map 格式直接使用Vec 格式逐项转为空值键 // [pattern1, pattern2] - {pattern1: , pattern2: }SettingsValue::from_file_value也遵循同样的双格式逻辑先尝试对象map解析再回退数组legacy解析。由于用户不会降级只需前向迁移。若 TOML 值既不是字符串数组也不是映射损坏配置则回退到默认空映射与既有损坏设置的处理行为一致。三个设置操作方法对应 app/src/settings/ai.rs 中的三个方法add_cli_agent_footer_enabled_command(command)trim 后判空、去重以空字符串值插入键remove_cli_agent_footer_enabled_command(command)shift_remove删除键Agent 映射随键一并消失set_cli_agent_for_command(pattern, agent: OptionCLIAgent)None写空字符串Some(agent)写agent.to_serialized_name()仅当键已存在时更新。to_serialized_name/from_serialized_name定义于 cli_agent.rs是CLIAgent与字符串之间的序列化互转空字符串反序列化回CLIAgent::Unknown。对应的 TOML 示例设置界面之外直接查看/配置底层文件时[agents.third_party] # 新格式模式 - Agent 序列化名空字符串表示 CLI Agent cli_agent_toolbar_enabled_commands { my-claude-wrapper Claude, uber-cli Codex, legacy-cmd }检测链路matched_agent 如何携带 Agent技术规格TECH.md把检测链路的改造作为核心让bool匹配升级为「携带 Agent 的匹配」。编译后的正则单例CompiledCommandsForCodingAgentToolbar是缓存编译正则的单例模型将ToolbarCommandMap编译为「正则 Agent」对pub struct CompiledCommandsForCodingAgentToolbar { regexes: Vec(Regex, CLIAgent), }其parse遍历设置映射编译键为正则失败则跳过值经CLIAgent::from_serialized_name解析为具体 Agent。单例注册时订阅AISettingsChangedEvent::CLIAgentToolbarEnabledCommands变更事件任何增删改都会触发正则重建。匹配入口matched_agent返回OptionCLIAgentpub fn matched_agent(app: AppContext, command: str) - OptionCLIAgent { Self::as_ref(app) .regexes .iter() .find(|(regex, _)| regex.is_match(command)) .map(|(_, agent)| *agent) }is_match针对完整命令字符串进行匹配因此正则需要能覆盖包装脚本的整条命令例如.*my-claude-wrapper.*或直接写命令名。终端侧的检测顺序终端视图的detect_cli_agent_from_modeluse_agent_footer/mod.rs在命令成为长期运行命令后被调用检测顺序如下先走原生检测CLIAgent::detect解析命令首词支持跳过FOO1这类环境变量前缀、按 shell 别名表解析别名、再与各 Agent 的command_prefixes()比对同时检查aifx agent run claude特例若原生检测返回None回退到CompiledCommandsForCodingAgentToolbar::matched_agent命中用户自定义模式则返回该模式绑定的具体 Agent若返回的 Agent 来自自定义模式函数还会顺带返回自定义命令前缀命令首词供后续 UI 使用。这样模式命中不再无条件返回CLIAgent::Unknown而是把用户在设置中选择的 Agent 一路传递到会话创建。会话创建与完整 Agent 体验检测结果最终传给CLIAgentSessionsModel::set_session存储在CLIAgentSession.agent字段cli_agent_sessions/mod.rs。所有下游消费方都从这个会话读取 Agent工具栏渲染使用session.agent的图标、显示名与品牌色。品牌色在 cli_agent.rs 中定义例如 Claude 橙色、Gemini 蓝、Grok 近黑等Rich Input 提交策略由rich_input_submit_strategy(agent)选择use_agent_footer/mod.rs当前实现如下Agent提交策略Codex、OhMyPi、HermesBracketedPaste括号粘贴CopilotBracketedPasteDelayedEnter括号粘贴 延迟回车Claude、OpenCode、Gemini、Auggie、Grok、CursorCliDelayedEnter延迟回车Amp、Droid、Pi、Kiro、Goose、Vibe、Antigravity、WarpTui、UnknownInline直接写入斜杠菜单技能supported_skill_providers()决定 Rich Input 斜杠菜单展示哪些 skill provider例如 Claude 只显示SkillProvider::ClaudeCodex 显示 Agents/Claude/Codex 三个Unknown 为空通知会话携带 Agent 后通知可显示正确的显示名与图标。需要说明的是产品规格中描述的提交策略映射与当前源码实现存在细微差异如规格将 Claude 归为Inline、Copilot 归为DelayedEnter而源码实际为 Claude →DelayedEnter、Copilot →BracketedPasteDelayedEnter本文章以仓库当前代码为准。插件监听器与安装/更新芯片自定义模式一旦绑定到具体 Agent插件生命周期将自动生效无需额外改动OSC 777 哨兵路径插件发送warp://cli-agent的SessionStart事件时view.rs中约 10960 行register_listener被调用。只要is_agent_supported(CLIAgent::Claude)为真listener/mod.rs 当前对 Claude、OpenCode、Codex、Gemini、Auggie、Droid、Pi、OhMyPi、Grok、WarpTui 均返回 true监听器即注册成功而Unknown永远不会创建监听器Codex 主动注册Codex 使用 OSC 9 纯文本通知检测到CLIAgent::Codex后立即调用register_cli_agent_listener约 10069 行——自定义模式绑定 Codex 同样触发该路径安装/更新芯片plugin_manager_for(agent)plugin_manager/mod.rs返回对应 Agent 的插件管理器从而显示插件安装/更新 chip。简言之只要detect_cli_agent_from_model返回具体 Agent会话就会携带它整条插件链路注册监听器、安装 chip、更新 chip、富状态自动按该 Agent 运行与原生检测完全一致。aifx agent run claude 特例CLIAgent::detect中的is_aifx_agent_run_claude判断cli_agent.rs做了两件事命令以aifx agent run claude开头且用户属于 Uber 团队工作区团队 UID 匹配UBER_TEAM_UID。命中即返回CLIAgent::Claude无需任何配置。该特例保持原样、不随本次改动变化非 Uber 用户若希望获得相同效果只需添加自定义模式并绑定到 Claude。验证清单从设置到运行的一整套检查结合产品规格的 Validation 与成功标准推荐按以下清单验证设置界面每条命令的行内都出现下拉框下拉包含 CLI Agent无图标与除Unknown外的全部 Agent正确图标 显示名默认值新添加的命令默认 CLI Agent绑定验证添加my-claude-wrapper模式并绑定 Claude在终端运行该命令检查工具栏显示 Claude 图标与品牌、Rich Input 使用 Claude 的提交策略、插件未安装时出现安装 chip、通知显示 Claude Code插件监听绑定 Claude/Codex/OpenCode 的模式命中后插件生命周期install chip、update chip、监听器注册与原生检测一致持久化修改选择后重启 Warp下拉框仍保持所选状态设置随其他 AI 设置云端同步移除清理删除命令后重新添加同一条命令应恢复为默认 CLI Agent默认行为兼容不绑定 Agent 的既有模式仍产生CLIAgent::Unknown会话工具栏外观与旧版一致aifx 无回归Uber 团队成员运行aifx agent run claude仍识别为 Claude。风险与注意事项设置迁移自定义Deserialize必须同时处理旧VecString与新HashMap两种格式损坏值回退为空映射迭代顺序产品规格时代使用HashMap时列表顺序可能不保证当前实现改用IndexMap已解决此问题设置界面展示顺序稳定孤儿条目模式与 Agent 同处一个映射条目删除模式必然清除其 Agent 绑定无需额外清理逻辑。综上该方案通过「设置类型升级VecString→ 模式→Agent 映射 编译正则单例携带 Agentmatched_agent 检测链路传递detect_cli_agent_from_model 现有会话/插件机制复用」四步改造让自定义工具栏命令获得与原生 CLI Agent 完全一致的开箱体验。相关实现细节可继续在仓库中追溯settings/ai.rs、terminal/cli_agent.rs、terminal/view/use_agent_footer/mod.rs、terminal/cli_agent_sessions/listener/mod.rs 与 settings_view/cli_agents_page.rs。赞分享桌面应用开发者工具人工智能AI 应用AI Agent代码智能体【免费下载链接】warpWarp is an agentic development environment, born out of the terminal.项目地址https://gitcode.com/GitHub_Trending/wa/warp点击查看免费下载相关推荐Warp 自定义工具栏命令与 CLI Agent 关联从 CLIAgent::Unknown 到完整插件生命周期的设计实践Warp 自定义工具栏命令与 CLI Agent 关联从 CLIAgent::Unknown 到完整插件生命周期的设计实践 导读 本文以 specs/APP桌面应用开发者工具人工智能AI 应用AI Agent代码智能体为 omp-coding-agent 编写自定义工具Custom Tools从工厂模式到会话状态管理的完整实践指南为 omp coding agent 编写自定义工具Custom Tools从工厂模式到会话状态管理的完整实践指南 自定义工具Custom Tools人工智能AI Agent代码智能体工具调用CLIMCP Clientsclaude-agent-sdk-python 自定义 Agent 完整指南从 Markdown 文件到 AgentDefinition 编程式定义claude agent sdk python 自定义 Agent 完整指南从 Markdown 文件到 AgentDefinition 编程式定义 本指南以人工智能AI Agent工具调用MCP Clients大模型创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表