From 67ed9ae146472cf2e1e88db9546aade73b9d4cd6 Mon Sep 17 00:00:00 2001 From: Fini Date: Sat, 30 May 2026 15:49:11 +0800 Subject: [PATCH] fix(ai): align builtin model picker chrome --- .../src/widgets/ai_chat_model_picker.rs | 9 ++++-- .../op-editor-ui/src/widgets/ai_chat_panel.rs | 10 ++++++ .../src/widgets/ai_chat_panel/tests.rs | 32 ++++++++++++++++++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/crates/op-editor-ui/src/widgets/ai_chat_model_picker.rs b/crates/op-editor-ui/src/widgets/ai_chat_model_picker.rs index 79729fe58..585441b9f 100644 --- a/crates/op-editor-ui/src/widgets/ai_chat_model_picker.rs +++ b/crates/op-editor-ui/src/widgets/ai_chat_model_picker.rs @@ -460,7 +460,7 @@ fn with_alpha(color: Color, a: f32) -> Color { Color { a, ..color } } -fn paint_key_glyph(cx: &mut PaintCx<'_>, top_left: Point2D, size: f32, color: Color) { +pub(crate) fn paint_key_glyph(cx: &mut PaintCx<'_>, top_left: Point2D, size: f32, color: Color) { let cy = top_left.y + size * 0.5; let ring = Rect { origin: Point2D::new(top_left.x, cy - size * 0.28), @@ -515,7 +515,7 @@ fn provider_label(provider: AgentProvider) -> &'static str { match provider { AgentProvider::ClaudeCode => "ANTHROPIC", AgentProvider::CodexCli => "OPENAI", - AgentProvider::GeminiCli => "GEMINI", + AgentProvider::GeminiCli => "GOOGLE GEMINI", AgentProvider::GithubCopilot => "GITHUB COPILOT", AgentProvider::OpenCode => "OPENCODE", } @@ -682,6 +682,11 @@ mod tests { assert_eq!(group_label_for_entry(&entry), "OPENAI API KEY"); } + #[test] + fn gemini_provider_group_label_matches_ts_provider_name() { + assert_eq!(provider_label(AgentProvider::GeminiCli), "GOOGLE GEMINI"); + } + #[test] fn builtin_groups_stay_separate_when_ids_differ_but_provider_matches() { let models = vec![ diff --git a/crates/op-editor-ui/src/widgets/ai_chat_panel.rs b/crates/op-editor-ui/src/widgets/ai_chat_panel.rs index 3a0cdce42..211e9e5a1 100644 --- a/crates/op-editor-ui/src/widgets/ai_chat_panel.rs +++ b/crates/op-editor-ui/src/widgets/ai_chat_panel.rs @@ -632,6 +632,16 @@ impl<'a> Widget for AIChatPlaceholder<'a> { let selected = self.state.selected_model_entry(); let chip_color = self.theme.muted_foreground; match selected { + Some(entry) + if entry.builtin_provider_id.is_some() || entry.value.starts_with("builtin:") => + { + crate::widgets::ai_chat_model_picker::paint_key_glyph( + cx, + Point2D::new(model_x, toolbar_center_y - 7.0), + 14.0, + chip_color, + ) + } Some(entry) => crate::widgets::ai_chat_model_picker::paint_provider_logo( cx, entry.provider, diff --git a/crates/op-editor-ui/src/widgets/ai_chat_panel/tests.rs b/crates/op-editor-ui/src/widgets/ai_chat_panel/tests.rs index 4b5b4250c..bbfc1a1bf 100644 --- a/crates/op-editor-ui/src/widgets/ai_chat_panel/tests.rs +++ b/crates/op-editor-ui/src/widgets/ai_chat_panel/tests.rs @@ -204,6 +204,7 @@ fn body_rect_reserves_space_for_fixed_step_checklist() { #[derive(Default)] struct PanelPaintBackend { fills: Vec<(Rect, crate::Color)>, + stroke_lines: usize, } impl crate::RenderBackend for PanelPaintBackend { @@ -218,7 +219,9 @@ impl crate::RenderBackend for PanelPaintBackend { fn save(&mut self) {} fn restore(&mut self) {} fn translate(&mut self, _: Point2D) {} - fn stroke_line(&mut self, _: Point2D, _: Point2D, _: crate::Color, _: f32) {} + fn stroke_line(&mut self, _: Point2D, _: Point2D, _: crate::Color, _: f32) { + self.stroke_lines += 1; + } fn fill_round_rect(&mut self, _: Rect, _: f32, _: crate::Color) {} fn stroke_round_rect(&mut self, _: Rect, _: f32, _: crate::Color, _: f32) {} fn stroke_svg_path(&mut self, _: &str, _: Point2D, _: f32, _: crate::Color, _: f32) {} @@ -228,6 +231,33 @@ impl crate::RenderBackend for PanelPaintBackend { } } +#[test] +fn paint_model_chip_uses_key_glyph_for_builtin_model() { + let mut s = EditorState::new(); + s.chat + .available_models + .push(op_editor_core::chat::ModelEntry::builtin_with_display_name( + op_editor_core::chat::AgentProvider::CodexCli, + "builtin-minimax", + "MiniMax", + "builtin:builtin-minimax:MiniMax-M2.7", + "MiniMax-M2.7", + )); + let panel = AIChatPlaceholder::from_editor(&s); + let rect = Rect::xywh(0.0, 0.0, AI_CHAT_WIDTH, AI_CHAT_HEIGHT); + let mut backend = PanelPaintBackend::default(); + let mut cx = PaintCx { + backend: &mut backend, + }; + + panel.paint(&mut cx, rect); + + assert!( + backend.stroke_lines >= 2, + "built-in selected model chip should paint the TS-style Key glyph" + ); +} + fn has_fill_rect(fills: &[(Rect, crate::Color)], expected: Rect) -> bool { fills.iter().any(|(rect, _)| { (rect.origin.x - expected.origin.x).abs() < 1e-4