This commit is contained in:
@@ -43,7 +43,8 @@ fn review_tools() -> Vec<Tool> {
|
||||
),
|
||||
Tool::new(
|
||||
"read_file",
|
||||
"Read the content of a text file inside the repository.",
|
||||
"Read the content of a text file inside the repository. Every line is \
|
||||
prefixed with its absolute line number, even when only a range is read.",
|
||||
json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -128,18 +129,36 @@ async fn read_file(sandbox: &Sandbox, args: &Value) -> anyhow::Result<String> {
|
||||
let start = args.get("start_line").and_then(Value::as_u64);
|
||||
let end = args.get("end_line").and_then(Value::as_u64);
|
||||
|
||||
let output = if start.is_none() && end.is_none() {
|
||||
sandbox.exec(&["cat", "--", &path]).await?
|
||||
let (first_line, output) = if start.is_none() && end.is_none() {
|
||||
(1, sandbox.exec(&["cat", "--", &path]).await?)
|
||||
} else {
|
||||
let start = start.unwrap_or(1);
|
||||
let end = end
|
||||
.map(|line| line.to_string())
|
||||
.unwrap_or_else(|| "$".to_string());
|
||||
let range = format!("{start},{end}p");
|
||||
sandbox.exec(&["sed", "-n", &range, "--", &path]).await?
|
||||
|
||||
(
|
||||
start,
|
||||
sandbox.exec(&["sed", "-n", &range, "--", &path]).await?,
|
||||
)
|
||||
};
|
||||
|
||||
into_stdout(output)
|
||||
Ok(number_lines(&into_stdout(output)?, first_line))
|
||||
}
|
||||
|
||||
/// Préfixe chaque ligne par son numéro.
|
||||
///
|
||||
/// Le modèle doit citer une ligne précise pour ancrer son commentaire : sans
|
||||
/// numéros, il les compte lui-même et se décale de quelques lignes, ce qui place le
|
||||
/// commentaire à côté du code visé.
|
||||
fn number_lines(content: &str, first_line: u64) -> String {
|
||||
content
|
||||
.lines()
|
||||
.enumerate()
|
||||
.map(|(offset, line)| format!("{}:{line}", first_line + offset as u64))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
async fn grep(sandbox: &Sandbox, args: &Value) -> anyhow::Result<String> {
|
||||
@@ -243,4 +262,21 @@ mod tests {
|
||||
let err = required_str(&json!({}), "path").unwrap_err();
|
||||
assert!(err.to_string().contains("path"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lines_are_numbered_from_the_first_one() {
|
||||
assert_eq!(number_lines("a\nb\n", 1), "1:a\n2:b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_range_keeps_the_absolute_line_numbers() {
|
||||
// Un extrait lu à partir de la ligne 12 doit garder la numérotation du
|
||||
// fichier : sinon le modèle citerait des lignes décalées.
|
||||
assert_eq!(number_lines("x\ny", 12), "12:x\n13:y");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_empty_read_stays_empty() {
|
||||
assert_eq!(number_lines("", 1), "");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user