mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
cap to full
This commit is contained in:
@@ -268,7 +268,7 @@ For casual greetings, acknowledgements, or other one-off conversational messages
|
||||
When using the shell, you must adhere to the following guidelines:
|
||||
|
||||
- When searching for text or files, prefer using `rg` or `rg --files` respectively because `rg` is much faster than alternatives like `grep`. (If the `rg` command is not found, then use alternatives.)
|
||||
- Read files in chunks with a max chunk size of 250 lines. Do not use python scripts to attempt to output larger chunks of a file. Command line output will be truncated after 10 kilobytes or 256 lines of output, regardless of the command used.
|
||||
- Read files in chunks with a max chunk size of 250 lines. Do not use python scripts to attempt to output larger chunks of a file. Command line output is not truncated by Codex; the full stdout/stderr streams are available to clients (TUI and MCP). The model receives only a formatted summary of command output.
|
||||
|
||||
## `update_plan`
|
||||
|
||||
|
||||
@@ -726,11 +726,9 @@ impl Session {
|
||||
duration,
|
||||
exit_code,
|
||||
} = output;
|
||||
// Because stdout and stderr could each be up to 100 KiB, we send
|
||||
// truncated versions.
|
||||
const MAX_STREAM_OUTPUT: usize = 5 * 1024; // 5KiB
|
||||
let stdout = stdout.text.chars().take(MAX_STREAM_OUTPUT).collect();
|
||||
let stderr = stderr.text.chars().take(MAX_STREAM_OUTPUT).collect();
|
||||
// Send full stdout/stderr to clients; do not truncate.
|
||||
let stdout = stdout.text.clone();
|
||||
let stderr = stderr.text.clone();
|
||||
let formatted_output = format_exec_output_str(output);
|
||||
let aggregated_output: String = aggregated_output.text.clone();
|
||||
|
||||
@@ -2596,7 +2594,6 @@ fn format_exec_output(exec_output: &ExecToolCallOutput) -> String {
|
||||
// round to 1 decimal place
|
||||
let duration_seconds = ((duration.as_secs_f32()) * 10.0).round() / 10.0;
|
||||
|
||||
let formatted_output = format_exec_output_str(exec_output);
|
||||
let formatted_output = format_exec_output_str(exec_output);
|
||||
|
||||
let payload = ExecOutput {
|
||||
|
||||
@@ -31,8 +31,9 @@ use serde_bytes::ByteBuf;
|
||||
// Maximum we send for each stream, which is either:
|
||||
// - 10KiB OR
|
||||
// - 256 lines
|
||||
const MAX_STREAM_OUTPUT: usize = 10 * 1024;
|
||||
const MAX_STREAM_OUTPUT_LINES: usize = 256;
|
||||
// No caps: collect full stdout/stderr and aggregated output
|
||||
const MAX_STREAM_OUTPUT: usize = usize::MAX;
|
||||
const MAX_STREAM_OUTPUT_LINES: usize = usize::MAX;
|
||||
|
||||
const DEFAULT_TIMEOUT_MS: u64 = 10_000;
|
||||
|
||||
@@ -216,22 +217,8 @@ impl StreamOutput<Vec<u8>> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn copy_capped(
|
||||
dst: &mut Vec<u8>,
|
||||
src: &[u8],
|
||||
remaining_bytes: &mut usize,
|
||||
remaining_lines: &mut usize,
|
||||
) {
|
||||
for &b in src {
|
||||
if *remaining_bytes == 0 || *remaining_lines == 0 {
|
||||
break;
|
||||
}
|
||||
dst.push(b);
|
||||
*remaining_bytes = remaining_bytes.saturating_sub(1);
|
||||
if b == b'\n' {
|
||||
*remaining_lines = remaining_lines.saturating_sub(1);
|
||||
}
|
||||
}
|
||||
fn append_all(dst: &mut Vec<u8>, src: &[u8]) {
|
||||
dst.extend_from_slice(src);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -338,28 +325,13 @@ pub(crate) async fn consume_truncated_output(
|
||||
|
||||
drop(agg_tx);
|
||||
|
||||
let mut combined_buf = Vec::with_capacity(MAX_STREAM_OUTPUT.min(8 * 1024));
|
||||
let mut remaining_bytes = MAX_STREAM_OUTPUT;
|
||||
let mut remaining_lines = MAX_STREAM_OUTPUT_LINES;
|
||||
let mut combined_buf = Vec::with_capacity(8 * 1024);
|
||||
while let Ok(chunk) = agg_rx.recv().await {
|
||||
if remaining_bytes == 0 || remaining_lines == 0 {
|
||||
continue;
|
||||
}
|
||||
copy_capped(
|
||||
&mut combined_buf,
|
||||
&chunk,
|
||||
&mut remaining_bytes,
|
||||
&mut remaining_lines,
|
||||
);
|
||||
append_all(&mut combined_buf, &chunk);
|
||||
}
|
||||
let truncated = remaining_lines == 0 || remaining_bytes == 0;
|
||||
let aggregated_output = StreamOutput {
|
||||
text: combined_buf,
|
||||
truncated_after_lines: if truncated {
|
||||
Some((MAX_STREAM_OUTPUT_LINES - remaining_lines) as u32)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
truncated_after_lines: None,
|
||||
};
|
||||
|
||||
Ok(RawExecToolCallOutput {
|
||||
@@ -372,17 +344,16 @@ pub(crate) async fn consume_truncated_output(
|
||||
|
||||
async fn read_capped<R: AsyncRead + Unpin + Send + 'static>(
|
||||
mut reader: R,
|
||||
max_output: usize,
|
||||
max_lines: usize,
|
||||
_max_output: usize,
|
||||
_max_lines: usize,
|
||||
stream: Option<StdoutStream>,
|
||||
is_stderr: bool,
|
||||
aggregate_tx: Option<Sender<Vec<u8>>>,
|
||||
) -> io::Result<StreamOutput<Vec<u8>>> {
|
||||
let mut buf = Vec::with_capacity(max_output.min(8 * 1024));
|
||||
let mut buf = Vec::with_capacity(8 * 1024);
|
||||
let mut tmp = [0u8; 8192];
|
||||
|
||||
let mut remaining_bytes = max_output;
|
||||
let mut remaining_lines = max_lines;
|
||||
// No caps: append all bytes
|
||||
|
||||
loop {
|
||||
let n = reader.read(&mut tmp).await?;
|
||||
@@ -413,26 +384,13 @@ async fn read_capped<R: AsyncRead + Unpin + Send + 'static>(
|
||||
let _ = tx.send(tmp[..n].to_vec()).await;
|
||||
}
|
||||
|
||||
if remaining_bytes > 0 && remaining_lines > 0 {
|
||||
copy_capped(
|
||||
&mut buf,
|
||||
&tmp[..n],
|
||||
&mut remaining_bytes,
|
||||
&mut remaining_lines,
|
||||
);
|
||||
}
|
||||
// Continue reading to EOF to avoid back-pressure, but discard once caps are hit.
|
||||
append_all(&mut buf, &tmp[..n]);
|
||||
// Continue reading to EOF to avoid back-pressure
|
||||
}
|
||||
|
||||
let truncated = remaining_lines == 0 || remaining_bytes == 0;
|
||||
|
||||
Ok(StreamOutput {
|
||||
text: buf,
|
||||
truncated_after_lines: if truncated {
|
||||
Some((max_lines - remaining_lines) as u32)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
truncated_after_lines: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -70,12 +70,12 @@ async fn truncates_output_lines() {
|
||||
|
||||
let output = run_test_cmd(tmp, cmd).await.unwrap();
|
||||
|
||||
let expected_output = (1..=256)
|
||||
let expected_output = (1..=300)
|
||||
.map(|i| format!("{i}\n"))
|
||||
.collect::<Vec<_>>()
|
||||
.join("");
|
||||
assert_eq!(output.stdout.text, expected_output);
|
||||
assert_eq!(output.stdout.truncated_after_lines, Some(256));
|
||||
assert_eq!(output.stdout.truncated_after_lines, None);
|
||||
}
|
||||
|
||||
/// Command succeeds with exit code 0 normally
|
||||
@@ -91,8 +91,8 @@ async fn truncates_output_bytes() {
|
||||
|
||||
let output = run_test_cmd(tmp, cmd).await.unwrap();
|
||||
|
||||
assert_eq!(output.stdout.text.len(), 10240);
|
||||
assert_eq!(output.stdout.truncated_after_lines, Some(10));
|
||||
assert!(output.stdout.text.len() >= 15000);
|
||||
assert_eq!(output.stdout.truncated_after_lines, None);
|
||||
}
|
||||
|
||||
/// Command not found returns exit code 127, this is not considered a sandbox error
|
||||
|
||||
Reference in New Issue
Block a user