Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2024-04-09 - Rust String Cloning Optimization
**Learning:** In Rust, building lists of string parts for joining (e.g., `vec![string1.clone(), string2.clone()].join(" ")`) is a common pattern that can lead to unnecessary heap allocations. This codebase frequently does this when formatting reports. When the source values are already `String`s, borrowing them as `&str` and pushing them to a `Vec<&str>` before calling `.join()` entirely avoids these intermediate heap allocations. Additionally, calling `.to_string()` on static string slices just to appease a `Vec<String>` is wasteful when `Vec<&str>` works perfectly.
**Action:** When constructing strings from parts using `Vec` and `.join()`, look for opportunities to use a `Vec<&str>` populated with borrowed string slices (`.as_str()`) instead of a `Vec<String>` populated with cloned strings (`.clone()`).
42 changes: 42 additions & 0 deletions patch_pr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import sys

def replace_in_file(filepath, search_str, replace_str):
with open(filepath, 'r') as f:
content = f.read()

if search_str in content:
content = content.replace(search_str, replace_str)
with open(filepath, 'w') as f:
f.write(content)
print("Replacement successful.")
else:
print("Search string not found.")

search = """fn agent_detail(agent: &AgentSummary) -> String {
let mut parts = vec![agent.name.as_str()];
if let Some(description) = &agent.description {
parts.push(description.as_str());
}
if let Some(model) = &agent.model {
parts.push(model.as_str());
}
if let Some(reasoning) = &agent.reasoning_effort {
parts.push(reasoning.as_str());
}
parts.join(" · ")
}"""

replace = """fn agent_detail(agent: &AgentSummary) -> String {
let parts: Vec<&str> = [
Some(agent.name.as_str()),
agent.description.as_deref(),
agent.model.as_deref(),
agent.reasoning_effort.as_deref(),
]
.into_iter()
.flatten()
.collect();
parts.join(" · ")
}"""

replace_in_file('rust/crates/commands/src/lib.rs', search, replace)
34 changes: 17 additions & 17 deletions rust/crates/commands/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3290,16 +3290,15 @@ fn render_agents_report_json(cwd: &Path, agents: &[AgentSummary]) -> Value {
}

fn agent_detail(agent: &AgentSummary) -> String {
let mut parts = vec![agent.name.clone()];
if let Some(description) = &agent.description {
parts.push(description.clone());
}
if let Some(model) = &agent.model {
parts.push(model.clone());
}
if let Some(reasoning) = &agent.reasoning_effort {
parts.push(reasoning.clone());
}
let parts: Vec<&str> = [
Some(agent.name.as_str()),
agent.description.as_deref(),
agent.model.as_deref(),
agent.reasoning_effort.as_deref(),
]
.into_iter()
.flatten()
.collect();
parts.join(" · ")
}

Expand Down Expand Up @@ -3333,13 +3332,14 @@ fn render_skills_report(skills: &[SkillSummary]) -> String {

lines.push(format!("{}:", scope.label()));
for skill in group {
let mut parts = vec![skill.name.clone()];
if let Some(description) = &skill.description {
parts.push(description.clone());
}
if let Some(detail) = skill.origin.detail_label() {
parts.push(detail.to_string());
}
let parts: Vec<&str> = [
Some(skill.name.as_str()),
skill.description.as_deref(),
skill.origin.detail_label(),
]
.into_iter()
.flatten()
.collect();
let detail = parts.join(" · ");
match skill.shadowed_by {
Some(winner) => lines.push(format!(" (shadowed by {}) {detail}", winner.label())),
Expand Down
Loading