Skip to content

Commit 27f2aa2

Browse files
committed
feat (ml-tooling): cap by lines instead of number of chars
1 parent 117708f commit 27f2aa2

6 files changed

Lines changed: 67 additions & 61 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "isanagent"
3-
version = "0.3.1"
3+
version = "0.4.0"
44
edition = "2021"
55
license = "Apache-2.0"
66
repository = "https://github.com/altaidevorg/isanagent"

src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,6 @@ Enable [api], [slack], or [email] (with enabled = true) so the agent can receive
473473
max_output_chars: max_web_output_chars,
474474
}));
475475
tools.register(Box::new(ArxivFetchTool {
476-
max_output_chars: max_web_output_chars,
477476
workspace_dir: workspace.dir.clone(),
478477
}));
479478
tools.register(Box::new(HfHubFileFetchTool {

src/tools/builtin.rs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl Tool for ReadFileTool {
138138
}
139139

140140
fn description(&self) -> &str {
141-
"Read the contents of a local file. Provide the absolute or relative path to the file. You can optionally read specific lines by specifying start_line and end_line (1-indexed, inclusive) capped at a maximum of 100 lines per call."
141+
"Read the contents of a local file. Provide the absolute or relative path to the file. You can read specific lines by specifying start_line and end_line (1-indexed, inclusive) capped at a maximum of 100 lines per call, so you can call this tool multiple times to read a file with more than 100 lines when needed."
142142
}
143143

144144
fn parameters(&self) -> Value {
@@ -151,14 +151,14 @@ impl Tool for ReadFileTool {
151151
},
152152
"start_line": {
153153
"type": "integer",
154-
"description": "Optional starting line number (1-indexed, inclusive)"
154+
"description": "Starting line number (1-indexed, inclusive)"
155155
},
156156
"end_line": {
157157
"type": "integer",
158-
"description": "Optional ending line number (1-indexed, inclusive)"
158+
"description": "Ending line number (1-indexed, inclusive)"
159159
}
160160
},
161-
"required": ["path"]
161+
"required": ["path", "start_line", "end_line"]
162162
})
163163
}
164164

@@ -170,22 +170,19 @@ impl Tool for ReadFileTool {
170170

171171
let actual_path = resolve_path(path_str, &self.workspace_dir, self.restrict_to_workspace)?;
172172

173-
let start_line = args.get("start_line").and_then(|v| v.as_u64());
174-
let end_line = args.get("end_line").and_then(|v| v.as_u64());
173+
let start_line = args
174+
.get("start_line")
175+
.and_then(|v| v.as_u64())
176+
.ok_or("Missing 'start_line' argument")?;
177+
let end_line = args
178+
.get("end_line")
179+
.and_then(|v| v.as_u64())
180+
.ok_or("Missing 'end_line' argument")?;
175181

176182
let content = fs::read_to_string(&actual_path).map_err(|e| e.to_string())?;
177183

178-
if start_line.is_none() && end_line.is_none() {
179-
// No lines specified, check total lines
180-
let total_lines = content.lines().count();
181-
if total_lines > 100 {
182-
return Err(format!("File is too large ({} lines). Please specify start_line and end_line to read a maximum of 100 lines at a time.", total_lines));
183-
}
184-
return Ok(content);
185-
}
186-
187-
let start = start_line.unwrap_or(1).max(1) as usize;
188-
let end = end_line.unwrap_or(start as u64 + 99) as usize;
184+
let start = start_line.max(1) as usize;
185+
let end = end_line as usize;
189186

190187
if end < start {
191188
return Err("end_line must be greater than or equal to start_line".to_string());
@@ -201,8 +198,7 @@ impl Tool for ReadFileTool {
201198

202199
let snippet: Vec<String> = lines[actual_start - 1..actual_end]
203200
.iter()
204-
.enumerate()
205-
.map(|(i, l)| format!("{:4}: {}", actual_start + i, l))
201+
.map(|l| l.to_string())
206202
.collect();
207203

208204
Ok(snippet.join("\n"))

src/tools/execution.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -638,10 +638,10 @@ impl Tool for ExecutionReadLogTool {
638638
"job_id": { "type": "string", "description": "The job ID to read logs from. Provide either this or run_id." },
639639
"run_id": { "type": "string", "description": "The run ID to read logs from. Provide either this or job_id." },
640640
"stream": { "type": "string", "enum": ["stdout", "stderr"], "description": "Which stream to read." },
641-
"start_line": { "type": "integer", "description": "Optional starting line number (1-indexed, inclusive)" },
642-
"end_line": { "type": "integer", "description": "Optional ending line number (1-indexed, inclusive)" }
641+
"start_line": { "type": "integer", "description": "Starting line number (1-indexed, inclusive)" },
642+
"end_line": { "type": "integer", "description": "Ending line number (1-indexed, inclusive)" }
643643
},
644-
"required": ["stream"]
644+
"required": ["stream", "start_line", "end_line"]
645645
})
646646
}
647647

@@ -650,8 +650,14 @@ impl Tool for ExecutionReadLogTool {
650650
.get("stream")
651651
.and_then(|v| v.as_str())
652652
.unwrap_or("stdout");
653-
let start_line = args.get("start_line").and_then(|v| v.as_u64());
654-
let end_line = args.get("end_line").and_then(|v| v.as_u64());
653+
let start_line = args
654+
.get("start_line")
655+
.and_then(|v| v.as_u64())
656+
.ok_or("Missing 'start_line' argument")?;
657+
let end_line = args
658+
.get("end_line")
659+
.and_then(|v| v.as_u64())
660+
.ok_or("Missing 'end_line' argument")?;
655661

656662
let run_id;
657663
let mut sid = None;
@@ -725,8 +731,8 @@ impl Tool for ExecutionReadLogTool {
725731

726732
let mut reader = BufReader::new(file);
727733

728-
let start = start_line.unwrap_or(1).max(1) as usize;
729-
let end = end_line.unwrap_or(start as u64 + 99) as usize;
734+
let start = start_line.max(1) as usize;
735+
let end = end_line as usize;
730736

731737
if end < start {
732738
return Err("end_line must be greater than or equal to start_line".to_string());
@@ -744,11 +750,7 @@ impl Tool for ExecutionReadLogTool {
744750
Ok(0) => break,
745751
Ok(_) => {
746752
if current_line >= start && current_line <= actual_end {
747-
lines.push(format!(
748-
"{:4}: {}",
749-
current_line,
750-
buf.trim_end_matches(&['\r', '\n'][..])
751-
));
753+
lines.push(buf.trim_end_matches(&['\r', '\n'][..]).to_string());
752754
}
753755
current_line += 1;
754756
if current_line > actual_end {

src/tools/ml_domain.rs

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ impl Tool for ArxivSearchTool {
131131

132132
/// Fetch one arXiv abstract page (abs HTML) by id.
133133
pub struct ArxivFetchTool {
134-
pub max_output_chars: usize,
135134
pub workspace_dir: std::path::PathBuf,
136135
}
137136

@@ -166,20 +165,27 @@ impl Tool for ArxivFetchTool {
166165
return Err("invalid arxiv_id".to_string());
167166
}
168167

169-
let url = format!("https://arxiv.org/html/{}", id);
168+
let arxiv2md_url = format!("https://arxiv2md.org/api/markdown?url={}", id);
170169

171170
let client = reqwest::Client::builder()
172171
.user_agent(HF_USER_AGENT)
173172
.build()
174173
.map_err(|e| e.to_string())?;
175174

176-
let resp = client
177-
.get(&url)
178-
.send()
179-
.await
180-
.map_err(|e| format!("arxiv_fetch request: {}", e))?;
175+
let arxiv2md_resp = client.get(&arxiv2md_url).send().await;
181176

182-
let full_content = if !resp.status().is_success() {
177+
let mut html_markdown_content = String::new();
178+
if let Ok(resp) = arxiv2md_resp {
179+
if resp.status().is_success() {
180+
if let Ok(text) = resp.text().await {
181+
if text.lines().count() >= 30 {
182+
html_markdown_content = text;
183+
}
184+
}
185+
}
186+
}
187+
188+
let full_content = if html_markdown_content.is_empty() {
183189
let pdf_url = format!("https://arxiv.org/pdf/{}.pdf", id);
184190
let pdf_resp = client
185191
.get(&pdf_url)
@@ -189,7 +195,7 @@ impl Tool for ArxivFetchTool {
189195

190196
if !pdf_resp.status().is_success() {
191197
return Err(format!(
192-
"arxiv_fetch HTTP {} (HTML not found, and PDF not found for {})",
198+
"arxiv_fetch HTTP {} (PDF not found for {})",
193199
pdf_resp.status(),
194200
id
195201
));
@@ -203,12 +209,7 @@ impl Tool for ArxivFetchTool {
203209

204210
crate::utils::extract_markdown_from_pdf_bytes(&pdf_bytes)?
205211
} else {
206-
let html_content = resp
207-
.text()
208-
.await
209-
.map_err(|e| format!("arxiv_fetch body: {}", e))?;
210-
211-
htmd::convert(&html_content).map_err(|e| format!("html to markdown error: {}", e))?
212+
html_markdown_content
212213
};
213214

214215
let downloads_dir = self
@@ -222,20 +223,28 @@ impl Tool for ArxivFetchTool {
222223
.await
223224
.map_err(|e| e.to_string())?;
224225

225-
let safe_limit = self.max_output_chars.saturating_sub(1000).max(1000);
226-
let mut body = full_content.clone();
227-
crate::utils::truncate_utf8_safe(&mut body, safe_limit, "\n... [TRUNCATED]");
228-
229226
let total_lines = full_content.lines().count();
227+
let max_preview_lines = 50;
230228

231-
Ok(format!(
232-
"{body}\n\n---\nSystem: The full response ({} lines, {} bytes) was saved to `{}`. \
233-
If this preview is truncated, use the `read_file` tool with `start_line` and `end_line` arguments \
234-
on that path to incrementally read the rest of the content and/or use the `search_text` tool to find specific information.",
235-
total_lines,
236-
full_content.len(),
237-
file_path.display()
238-
))
229+
if total_lines <= max_preview_lines {
230+
Ok(format!(
231+
"{full_content}\n\n---\nFull paper ({total_lines} lines) saved to `{}`.",
232+
file_path.display()
233+
))
234+
} else {
235+
let preview: String = full_content
236+
.lines()
237+
.take(max_preview_lines)
238+
.collect::<Vec<_>>()
239+
.join("\n");
240+
241+
Ok(format!(
242+
"{preview}\n\n---\n[TRUNCATED] Showing first {max_preview_lines} of {total_lines} lines. \
243+
Full content saved to `{}`. Use `read_file` with `start_line` and `end_line` to read \
244+
the rest, or `search_text` to find specific information.",
245+
file_path.display()
246+
))
247+
}
239248
}
240249
}
241250

0 commit comments

Comments
 (0)