You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"Execute a shell command and return its output (60s timeout). Host details (OS/shell/path style) are provided in RUNTIME CONTEXT each turn; write commands for that host. Prefer first-class tools (`search_text`, `read_file`, `glob_files`, `web_fetch`) before shell one-liners, especially for grep/cat/wc style tasks. \
1137
-
On **Windows** this runs under **cmd /C** one string: nested double-quotes often break remote **ssh** compound commands (e.g. `ssh user@host \"mkdir -p /tmp/x && cmd\"`). Prefer a **single** remote argument without inner double-quotes, use **execution_* / SSH harness** for remote work, or run **two** short exec calls instead of one over-quoted line."
1138
-
}
1139
-
1140
-
fnparameters(&self) -> Value{
1141
-
serde_json::json!({
1142
-
"type":"object",
1143
-
"properties":{
1144
-
"command":{
1145
-
"type":"string",
1146
-
"description":"The shell command to execute"
1147
-
},
1148
-
"working_dir":{
1149
-
"type":"string",
1150
-
"description":"Optional relative working directory for the command"
1151
-
},
1152
-
"timeout_secs":{
1153
-
"type":"integer",
1154
-
"description":"Optional timeout in seconds (defaults to 60, max 3600)"
1155
-
},
1156
-
"description":{
1157
-
"type":"string",
1158
-
"description":"Short description of what this command is trying to achieve (used for UI and audits)"
result.push_str("\n\n[advisory] Prefer `search_text` for code/log discovery and `read_file` for file reads; shell grep/cat pipelines are less portable across hosts.");
1242
-
}
1243
-
// Truncate if massive (the exit marker is appended afterwards, so it is never cut).
1244
-
if result.len() > 10000{
1245
-
// Step back to a char boundary at/below the 10 KB cap so we never slice
1246
-
// through a multi-byte UTF-8 sequence (e.g. Turkish text or emoji straddling
1247
-
// the limit), which would panic. Matches the is_char_boundary idiom used by
if result.is_empty() && failure_exit_code.is_none(){
1199
+
result = "(no output)".to_string();
1200
+
}else{
1201
+
if grep_like {
1202
+
result.push_str("\n\n[advisory] Prefer `search_text` for code/log discovery and `read_file` for file reads; shell grep/cat pipelines are less portable across hosts.");
1203
+
}
1204
+
if result.len() > 10000{
1205
+
letmut cut = 10000;
1206
+
while cut > 0 && !result.is_char_boundary(cut){
1207
+
cut -= 1;
1263
1208
}
1209
+
result = format!(
1210
+
"{}\n... (truncated, {} more chars)",
1211
+
&result[..cut],
1212
+
result.len() - cut
1213
+
);
1214
+
}
1215
+
ifletSome(code) = failure_exit_code {
1216
+
result.push_str(&format!("\nExit code: {code}"));
1264
1217
}
1265
-
Ok(Err(e)) => Err(format!("Failed to execute command: {}", e)),
1266
-
Err(_) => Err(format!("Command timed out after {} seconds", timeout_secs)),
1218
+
}
1219
+
1220
+
Ok(ShellExecOutcome{
1221
+
content: result,
1222
+
failure_exit_code,
1223
+
})
1224
+
}
1225
+
}
1226
+
1227
+
#[async_trait]
1228
+
implToolforShellExecTool{
1229
+
fnname(&self) -> &str{
1230
+
"exec"
1231
+
}
1232
+
1233
+
fndescription(&self) -> &str{
1234
+
"Execute a shell command and return its output (60s timeout). Host details (OS/shell/path style) are provided in RUNTIME CONTEXT each turn; write commands for that host. Prefer first-class tools (`search_text`, `read_file`, `glob_files`, `web_fetch`) before shell one-liners, especially for grep/cat/wc style tasks. \
1235
+
On **Windows** this runs under **cmd /C** one string: nested double-quotes often break remote **ssh** compound commands (e.g. `ssh user@host \"mkdir -p /tmp/x && cmd\"`). Prefer a **single** remote argument without inner double-quotes, use **execution_* / SSH harness** for remote work, or run **two** short exec calls instead of one over-quoted line."
1236
+
}
1237
+
1238
+
fnparameters(&self) -> Value{
1239
+
serde_json::json!({
1240
+
"type":"object",
1241
+
"properties":{
1242
+
"command":{
1243
+
"type":"string",
1244
+
"description":"The shell command to execute"
1245
+
},
1246
+
"working_dir":{
1247
+
"type":"string",
1248
+
"description":"Optional relative working directory for the command"
1249
+
},
1250
+
"timeout_secs":{
1251
+
"type":"integer",
1252
+
"description":"Optional timeout in seconds (defaults to 60, max 3600)"
1253
+
},
1254
+
"description":{
1255
+
"type":"string",
1256
+
"description":"Short description of what this command is trying to achieve (used for UI and audits)"
0 commit comments