fix(ai): disable mcp port while running

This commit is contained in:
Fini 2026-05-30 03:30:35 +08:00
parent a91645642d
commit cf26ccfdbc
6 changed files with 59 additions and 6 deletions

View file

@ -99,11 +99,11 @@ fn cli_cell_rect(content: Rect, idx: usize) -> Rect {
}
}
pub fn hit_test(content: Rect, scrolled: Point2D) -> McpHit {
pub fn hit_test(content: Rect, settings: &AgentSettings, scrolled: Point2D) -> McpHit {
if rect_contains(server_button_rect(content), scrolled) {
return McpHit::ToggleServer;
}
if rect_contains(port_field_rect(content), scrolled) {
if !settings.mcp_server.running && rect_contains(port_field_rect(content), scrolled) {
return McpHit::FocusPort;
}
for (i, cli) in McpCli::ALL.iter().enumerate() {
@ -229,7 +229,8 @@ fn paint_server_card(
Point2D::new(port_field_x - 8.0 - port_label_w, mid_y + 4.0),
);
let port_field = port_field_rect(content);
let focused = matches!(settings.focus, Some(SettingsFocus::McpPort));
let port_editable = !running;
let focused = port_editable && matches!(settings.focus, Some(SettingsFocus::McpPort));
let port_str = if focused {
ui.settings_input_draft.clone()
} else {
@ -247,7 +248,11 @@ fn paint_server_card(
&port_str,
"system-ui",
12.0,
to_jian(theme.foreground),
to_jian(if port_editable {
theme.foreground
} else {
theme.muted_foreground
}),
Point2D::new(0.0, 0.0),
);
let port_x = port_field.origin.x + (PORT_FIELD_W - port_w) / 2.0;

View file

@ -148,7 +148,7 @@ impl<'a> AgentSettingsPanel<'a> {
}
}
AgentSettingsTab::Mcp => {
match agent_settings_mcp::hit_test(content_rect(panel), scrolled) {
match agent_settings_mcp::hit_test(content_rect(panel), &self.settings, scrolled) {
McpHit::ToggleServer => return AgentSettingsHit::ToggleMcpServer,
McpHit::ToggleCli(cli) => return AgentSettingsHit::ToggleMcpCli(cli),
McpHit::FocusPort => return AgentSettingsHit::FocusMcpPort,

View file

@ -131,3 +131,21 @@ fn hit_test_resolves_builtin_agent_compact_edit_button() {
AgentSettingsHit::EditBuiltinAgent(0)
);
}
#[test]
fn mcp_port_field_is_not_focusable_while_server_is_running() {
let mut state = EditorState::default();
state.editor_ui.agent_settings.tab = AgentSettingsTab::Mcp;
state.editor_ui.agent_settings.mcp_server.running = true;
let panel = AgentSettingsPanel::for_editor(&state);
let rect = panel.rect(1200.0, 800.0);
let content_x = rect.origin.x + 200.0 + 24.0;
let content_y = rect.origin.y + 24.0;
let content_w = rect.size.x - 200.0 - 48.0;
let server_card_top = content_y + 36.0;
let button_x = content_x + content_w - 16.0 - 72.0;
let port_x = button_x - 8.0 - 64.0;
let point = crate::Point2D::new(port_x + 32.0, server_card_top + 26.0);
assert_eq!(panel.hit_test(rect, point), AgentSettingsHit::Inside);
}

View file

@ -1,5 +1,5 @@
use super::WidgetHostNative;
use op_editor_core::agent_settings::{BuiltinAgentField, SettingsFocus};
use op_editor_core::agent_settings::{AgentSettingsTab, BuiltinAgentField, SettingsFocus};
use op_editor_ui::widgets::agent_settings_panel::AgentSettingsPanel;
#[test]
@ -109,3 +109,31 @@ fn builtin_agent_compact_edit_focuses_display_name_form() {
"MiniMax"
);
}
#[test]
fn starting_mcp_server_commits_port_draft_and_clears_focus() {
let mut host = WidgetHostNative::new();
host.editor_state_mut().editor_ui.agent_settings.tab = AgentSettingsTab::Mcp;
host.editor_state_mut().editor_ui.agent_settings.focus = Some(SettingsFocus::McpPort);
host.editor_state_mut().editor_ui.settings_input_draft = "3101".into();
let panel = AgentSettingsPanel::for_editor(host.editor_state());
let rect = panel.rect(1200.0, 800.0);
let content_x = rect.origin.x + 200.0 + 24.0;
let content_y = rect.origin.y + 24.0;
let content_w = rect.size.x - 200.0 - 48.0;
let server_card_top = content_y + 36.0;
let button_x = content_x + content_w - 16.0 - 72.0;
assert!(host.dispatch_agent_settings_press(
button_x + 36.0,
server_card_top + 26.0,
1200.0,
800.0
));
let state = host.editor_state();
assert!(state.editor_ui.agent_settings.mcp_server.running);
assert_eq!(state.editor_ui.agent_settings.mcp_server.port, 3101);
assert!(state.editor_ui.agent_settings.focus.is_none());
assert!(state.editor_ui.settings_input_draft.is_empty());
}

View file

@ -77,6 +77,7 @@ impl WidgetHostNative {
self.editor_state.rebuild_chat_models();
}
AgentSettingsHit::ToggleMcpServer => {
self.commit_settings_focus_if_any();
let v = &mut self
.editor_state
.editor_ui

View file

@ -760,6 +760,7 @@ impl WidgetHost {
self.editor_state.rebuild_chat_models();
}
AgentSettingsHit::ToggleMcpServer => {
self.commit_settings_focus();
self.editor_state
.editor_ui
.agent_settings