Skip to content

Commit c4c6e07

Browse files
committed
fix(agents): sort agent list alphabetically for deterministic output
Fixes bounty issue #1510 The agent list command returned agents in non-deterministic order because HashMap iteration and fs::read_dir() don't guarantee ordering. This caused CI snapshot failures when comparing outputs across runs. Changes: - Sort filtered agents by name in run_list() before displaying - Sort results in AgentRegistry::list(), list_primary(), list_subagents() - Sort results in AgentRegistry::names()
1 parent 8f839ec commit c4c6e07

2 files changed

Lines changed: 20 additions & 7 deletions

File tree

cortex-agents/src/registry.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,29 +135,37 @@ impl AgentRegistry {
135135

136136
/// List all agents.
137137
pub async fn list(&self) -> Vec<AgentInfo> {
138-
self.agents.read().await.values().cloned().collect()
138+
let mut agents: Vec<AgentInfo> = self.agents.read().await.values().cloned().collect();
139+
agents.sort_by(|a, b| a.name.cmp(&b.name));
140+
agents
139141
}
140142

141143
/// List primary agents (user-facing).
142144
pub async fn list_primary(&self) -> Vec<AgentInfo> {
143-
self.agents
145+
let mut agents: Vec<AgentInfo> = self
146+
.agents
144147
.read()
145148
.await
146149
.values()
147150
.filter(|a| !a.hidden && matches!(a.mode, AgentMode::Primary | AgentMode::All))
148151
.cloned()
149-
.collect()
152+
.collect();
153+
agents.sort_by(|a, b| a.name.cmp(&b.name));
154+
agents
150155
}
151156

152157
/// List sub-agents.
153158
pub async fn list_subagents(&self) -> Vec<AgentInfo> {
154-
self.agents
159+
let mut agents: Vec<AgentInfo> = self
160+
.agents
155161
.read()
156162
.await
157163
.values()
158164
.filter(|a| matches!(a.mode, AgentMode::Subagent | AgentMode::All))
159165
.cloned()
160-
.collect()
166+
.collect();
167+
agents.sort_by(|a, b| a.name.cmp(&b.name));
168+
agents
161169
}
162170

163171
/// Unregister an agent.
@@ -172,7 +180,9 @@ impl AgentRegistry {
172180

173181
/// Get agent names.
174182
pub async fn names(&self) -> Vec<String> {
175-
self.agents.read().await.keys().cloned().collect()
183+
let mut names: Vec<String> = self.agents.read().await.keys().cloned().collect();
184+
names.sort();
185+
names
176186
}
177187

178188
/// Get agent by name if it's a valid subagent.

cortex-cli/src/agent_cmd.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ async fn run_list(args: ListArgs) -> Result<()> {
668668
let agents = load_all_agents()?;
669669

670670
// Filter agents
671-
let filtered: Vec<_> = agents
671+
let mut filtered: Vec<_> = agents
672672
.iter()
673673
.filter(|a| {
674674
// Filter by visibility
@@ -686,6 +686,9 @@ async fn run_list(args: ListArgs) -> Result<()> {
686686
})
687687
.collect();
688688

689+
// Sort agents alphabetically by name for deterministic output
690+
filtered.sort_by(|a, b| a.name.cmp(&b.name));
691+
689692
if args.json {
690693
let json = serde_json::to_string_pretty(&filtered)?;
691694
println!("{json}");

0 commit comments

Comments
 (0)