agent_ui: Add section for skills and rules in ellipsis menu (#57404)

Closes AI-291

This PR adds some new menu items in the agent panel's ellipsis menu to
make it easier to 1) create a new skill, 2) manage all existing skills
through the settings window, 3) open project and global AGENTS.md file,
if it exists.

Minor UI note: I'm adding an ellipsis character to the menu items in
which you need to do something else in a different view to fulfill the
item's label. For example, "Create Skill…" takes the ellipsis because
clicking on the menu item itself doesn't create the skill, but it takes
you to the place where you'll do that.

<img width="600" alt="Screenshot 2026-05-21 at 10  32@2x"
src="https://github.com/user-attachments/assets/1bfdd423-bd75-4c62-97ba-84130035ede8"
/>

Release Notes:

- N/A
This commit is contained in:
Danilo Leal 2026-05-21 16:37:55 -03:00 committed by GitHub
parent 7ec36d3661
commit d61ffb8e6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -10,7 +10,7 @@ use std::{
};
use acp_thread::{AcpThread, AcpThreadEvent, MentionUri, ThreadStatus};
use agent::{ContextServerRegistry, SharedThread, ThreadStore};
use agent::{ContextServerRegistry, SharedThread, ThreadStore, UserAgentsMd};
use agent_client_protocol::schema as acp;
use agent_servers::AgentServer;
use collections::HashSet;
@ -4780,6 +4780,28 @@ impl AgentPanel {
.active_conversation_view()
.is_some_and(|conversation_view| conversation_view.read(cx).supports_logout(cx));
let project_agents_md_path: Option<PathBuf> = self
.project
.read(cx)
.visible_worktrees(cx)
.next()
.and_then(|worktree| {
let worktree = worktree.read(cx);
let rel_path = util::rel_path::RelPath::unix("AGENTS.md").ok()?;
let entry = worktree.entry_for_path(rel_path)?;
if entry.is_file() {
Some(worktree.absolutize(rel_path))
} else {
None
}
});
let global_agents_md_loaded = UserAgentsMd::global(cx)
.and_then(|md| md.content())
.is_some();
let workspace = self.workspace.clone();
PopoverMenu::new("agent-options-menu")
.trigger_with_tooltip(
IconButton::new("agent-options-menu", IconName::Ellipsis)
@ -4821,8 +4843,9 @@ impl AgentPanel {
if !showing_terminal {
menu = menu
.header("MCP Servers")
.action("Add Custom Server…", Box::new(AddContextServer))
.action(
"View Server Extensions",
"Install New Servers…",
Box::new(zed_actions::Extensions {
category_filter: Some(
zed_actions::ExtensionCategoryFilter::ContextServers,
@ -4830,16 +4853,81 @@ impl AgentPanel {
id: None,
}),
)
.action("Add Custom Server…", Box::new(AddContextServer))
.separator()
.header("Skills")
.entry(
"Create Skill…",
Some(Box::new(OpenRulesLibrary::default())),
|window, cx| {
window.dispatch_action(Box::new(OpenSkillCreator), cx);
},
)
.entry("Manage Skills…", None, |window, cx| {
window.dispatch_action(
Box::new(zed_actions::OpenSettingsAt {
path: "agent.skills".to_string(),
}),
cx,
);
})
.separator();
menu = menu.entry(
"Skills",
Some(Box::new(OpenRulesLibrary::default())),
|window, cx| {
window.dispatch_action(Box::new(OpenSkillCreator), cx);
},
);
if project_agents_md_path.is_some() || global_agents_md_loaded {
menu = menu.header("Rules");
if global_agents_md_loaded {
let workspace = workspace.clone();
menu = menu.entry(
"Open Global AGENTS.md",
None,
move |window, cx| {
workspace
.update(cx, |workspace, cx| {
workspace
.open_abs_path(
paths::agents_file().clone(),
workspace::OpenOptions {
focus: Some(true),
..Default::default()
},
window,
cx,
)
.detach_and_log_err(cx);
})
.log_err();
},
);
}
if let Some(path) = project_agents_md_path.clone() {
let workspace = workspace.clone();
menu = menu.entry(
"Open Project AGENTS.md",
None,
move |window, cx| {
let path = path.clone();
workspace
.update(cx, |workspace, cx| {
workspace
.open_abs_path(
path,
workspace::OpenOptions {
focus: Some(true),
..Default::default()
},
window,
cx,
)
.detach_and_log_err(cx);
})
.log_err();
},
);
}
menu = menu.separator();
}
menu = menu.action("Profiles", Box::new(ManageProfiles::default()));
}
@ -4849,6 +4937,9 @@ impl AgentPanel {
.separator()
.action("Toggle Threads Sidebar", Box::new(ToggleWorkspaceSidebar));
if has_auth_methods || supports_logout {
menu = menu.separator()
}
if has_auth_methods {
menu = menu.action("Reauthenticate", Box::new(ReauthenticateAgent))
}
@ -8173,12 +8264,12 @@ mod tests {
cx.run_until_parked();
assert!(
cx.debug_bounds("MENU_ITEM-Skills").is_some(),
"Skills menu item should be visible"
cx.debug_bounds("MENU_ITEM-Create Skill…").is_some(),
"Create Skill… menu item should be visible"
);
assert!(
cx.debug_bounds("KEY_BINDING-l").is_some(),
"Skills menu item should show the OpenRulesLibrary shortcut"
"Create Skill… menu item should show the OpenRulesLibrary shortcut"
);
}