Skip to content

Commit 4f161e0

Browse files
authored
Merge branch 'main' into add-github-action-for-nix
2 parents ab6411f + 0e5d72c commit 4f161e0

File tree

21 files changed

+330
-208
lines changed

21 files changed

+330
-208
lines changed

codex-rs/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.

codex-rs/core/src/default_client.rs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::sync::OnceLock;
2020
/// The full user agent string is returned from the mcp initialize response.
2121
/// Parenthesis will be added by Codex. This should only specify what goes inside of the parenthesis.
2222
pub static USER_AGENT_SUFFIX: LazyLock<Mutex<Option<String>>> = LazyLock::new(|| Mutex::new(None));
23-
23+
pub const DEFAULT_ORIGINATOR: &str = "codex_cli_rs";
2424
pub const CODEX_INTERNAL_ORIGINATOR_OVERRIDE_ENV_VAR: &str = "CODEX_INTERNAL_ORIGINATOR_OVERRIDE";
2525
#[derive(Debug, Clone)]
2626
pub struct Originator {
@@ -35,10 +35,11 @@ pub enum SetOriginatorError {
3535
AlreadyInitialized,
3636
}
3737

38-
fn init_originator_from_env() -> Originator {
39-
let default = "codex_cli_rs";
38+
fn get_originator_value(provided: Option<String>) -> Originator {
4039
let value = std::env::var(CODEX_INTERNAL_ORIGINATOR_OVERRIDE_ENV_VAR)
41-
.unwrap_or_else(|_| default.to_string());
40+
.ok()
41+
.or(provided)
42+
.unwrap_or(DEFAULT_ORIGINATOR.to_string());
4243

4344
match HeaderValue::from_str(&value) {
4445
Ok(header_value) => Originator {
@@ -48,31 +49,22 @@ fn init_originator_from_env() -> Originator {
4849
Err(e) => {
4950
tracing::error!("Unable to turn originator override {value} into header value: {e}");
5051
Originator {
51-
value: default.to_string(),
52-
header_value: HeaderValue::from_static(default),
52+
value: DEFAULT_ORIGINATOR.to_string(),
53+
header_value: HeaderValue::from_static(DEFAULT_ORIGINATOR),
5354
}
5455
}
5556
}
5657
}
5758

58-
fn build_originator(value: String) -> Result<Originator, SetOriginatorError> {
59-
let header_value =
60-
HeaderValue::from_str(&value).map_err(|_| SetOriginatorError::InvalidHeaderValue)?;
61-
Ok(Originator {
62-
value,
63-
header_value,
64-
})
65-
}
66-
67-
pub fn set_default_originator(value: &str) -> Result<(), SetOriginatorError> {
68-
let originator = build_originator(value.to_string())?;
59+
pub fn set_default_originator(value: String) -> Result<(), SetOriginatorError> {
60+
let originator = get_originator_value(Some(value));
6961
ORIGINATOR
7062
.set(originator)
7163
.map_err(|_| SetOriginatorError::AlreadyInitialized)
7264
}
7365

7466
pub fn originator() -> &'static Originator {
75-
ORIGINATOR.get_or_init(init_originator_from_env)
67+
ORIGINATOR.get_or_init(|| get_originator_value(None))
7668
}
7769

7870
pub fn get_codex_user_agent() -> String {

codex-rs/exec/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use codex_core::default_client::set_default_originator;
4848
use codex_core::find_conversation_path_by_id_str;
4949

5050
pub async fn run_main(cli: Cli, codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()> {
51-
if let Err(err) = set_default_originator("codex_exec") {
51+
if let Err(err) = set_default_originator("codex_exec".to_string()) {
5252
tracing::warn!(?err, "Failed to set codex exec originator override {err:?}");
5353
}
5454

codex-rs/exec/tests/suite/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Aggregates all former standalone integration tests as modules.
22
mod apply_patch;
33
mod auth_env;
4+
mod originator;
45
mod output_schema;
56
mod resume;
67
mod sandbox;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#![cfg(not(target_os = "windows"))]
2+
#![allow(clippy::expect_used, clippy::unwrap_used)]
3+
4+
use core_test_support::responses;
5+
use core_test_support::test_codex_exec::test_codex_exec;
6+
use wiremock::matchers::header;
7+
8+
/// Verify that when the server reports an error, `codex-exec` exits with a
9+
/// non-zero status code so automation can detect failures.
10+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
11+
async fn send_codex_exec_originator() -> anyhow::Result<()> {
12+
let test = test_codex_exec();
13+
14+
let server = responses::start_mock_server().await;
15+
let body = responses::sse(vec![
16+
responses::ev_response_created("response_1"),
17+
responses::ev_assistant_message("response_1", "Hello, world!"),
18+
responses::ev_completed("response_1"),
19+
]);
20+
responses::mount_sse_once_match(&server, header("Originator", "codex_exec"), body).await;
21+
22+
test.cmd_with_server(&server)
23+
.arg("--skip-git-repo-check")
24+
.arg("tell me something")
25+
.assert()
26+
.code(0);
27+
28+
Ok(())
29+
}
30+
31+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
32+
async fn supports_originator_override() -> anyhow::Result<()> {
33+
let test = test_codex_exec();
34+
35+
let server = responses::start_mock_server().await;
36+
let body = responses::sse(vec![
37+
responses::ev_response_created("response_1"),
38+
responses::ev_assistant_message("response_1", "Hello, world!"),
39+
responses::ev_completed("response_1"),
40+
]);
41+
responses::mount_sse_once_match(&server, header("Originator", "codex_exec_override"), body)
42+
.await;
43+
44+
test.cmd_with_server(&server)
45+
.env("CODEX_INTERNAL_ORIGINATOR_OVERRIDE", "codex_exec_override")
46+
.arg("--skip-git-repo-check")
47+
.arg("tell me something")
48+
.assert()
49+
.code(0);
50+
51+
Ok(())
52+
}

codex-rs/tui/src/app_backtrack.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,9 @@ impl App {
134134
/// Useful when switching sessions to ensure prior history remains visible.
135135
pub(crate) fn render_transcript_once(&mut self, tui: &mut tui::Tui) {
136136
if !self.transcript_cells.is_empty() {
137+
let width = tui.terminal.last_known_screen_size.width;
137138
for cell in &self.transcript_cells {
138-
tui.insert_history_lines(cell.transcript_lines());
139+
tui.insert_history_lines(cell.display_lines(width));
139140
}
140141
}
141142
}

codex-rs/tui/src/bottom_pane/chat_composer.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ use crate::bottom_pane::prompt_args::prompt_has_numeric_placeholders;
3838
use crate::slash_command::SlashCommand;
3939
use crate::slash_command::built_in_slash_commands;
4040
use crate::style::user_message_style;
41-
use crate::terminal_palette;
4241
use codex_protocol::custom_prompts::CustomPrompt;
4342
use codex_protocol::custom_prompts::PROMPTS_CMD_PREFIX;
4443

@@ -1533,7 +1532,7 @@ impl WidgetRef for ChatComposer {
15331532
}
15341533
}
15351534
}
1536-
let style = user_message_style(terminal_palette::default_bg());
1535+
let style = user_message_style();
15371536
let mut block_rect = composer_rect;
15381537
block_rect.y = composer_rect.y.saturating_sub(1);
15391538
block_rect.height = composer_rect.height.saturating_add(1);

codex-rs/tui/src/bottom_pane/list_selection_view.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use crate::render::RectExt as _;
2020
use crate::render::renderable::ColumnRenderable;
2121
use crate::render::renderable::Renderable;
2222
use crate::style::user_message_style;
23-
use crate::terminal_palette;
2423

2524
use super::CancellationEvent;
2625
use super::bottom_pane_view::BottomPaneView;
@@ -350,7 +349,7 @@ impl Renderable for ListSelectionView {
350349
.areas(area);
351350

352351
Block::default()
353-
.style(user_message_style(terminal_palette::default_bg()))
352+
.style(user_message_style())
354353
.render(content_area, buf);
355354

356355
let header_height = self

codex-rs/tui/src/custom_terminal.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ where
120120
/// Last known position of the cursor. Used to find the new area when the viewport is inlined
121121
/// and the terminal resized.
122122
pub last_known_cursor_pos: Position,
123+
124+
use_custom_flush: bool,
123125
}
124126

125127
impl<B> Drop for Terminal<B>
@@ -158,6 +160,7 @@ where
158160
viewport_area: Rect::new(0, cursor_pos.y, 0, 0),
159161
last_known_screen_size: screen_size,
160162
last_known_cursor_pos: cursor_pos,
163+
use_custom_flush: true,
161164
})
162165
}
163166

@@ -190,15 +193,24 @@ where
190193
pub fn flush(&mut self) -> io::Result<()> {
191194
let previous_buffer = &self.buffers[1 - self.current];
192195
let current_buffer = &self.buffers[self.current];
193-
let updates = diff_buffers(previous_buffer, current_buffer);
194-
if let Some(DrawCommand::Put { x, y, .. }) = updates
195-
.iter()
196-
.rev()
197-
.find(|cmd| matches!(cmd, DrawCommand::Put { .. }))
198-
{
199-
self.last_known_cursor_pos = Position { x: *x, y: *y };
196+
197+
if self.use_custom_flush {
198+
let updates = diff_buffers(previous_buffer, current_buffer);
199+
if let Some(DrawCommand::Put { x, y, .. }) = updates
200+
.iter()
201+
.rev()
202+
.find(|cmd| matches!(cmd, DrawCommand::Put { .. }))
203+
{
204+
self.last_known_cursor_pos = Position { x: *x, y: *y };
205+
}
206+
draw(&mut self.backend, updates.into_iter())
207+
} else {
208+
let updates = previous_buffer.diff(current_buffer);
209+
if let Some((x, y, _)) = updates.last() {
210+
self.last_known_cursor_pos = Position { x: *x, y: *y };
211+
}
212+
self.backend.draw(updates.into_iter())
200213
}
201-
draw(&mut self.backend, updates.into_iter())
202214
}
203215

204216
/// Updates the Terminal so that internal buffers match the requested area.
@@ -408,11 +420,13 @@ fn diff_buffers<'a>(a: &'a Buffer, b: &'a Buffer) -> Vec<DrawCommand<'a>> {
408420

409421
let x = row
410422
.iter()
411-
.rposition(|cell| cell.symbol() != " " || cell.bg != bg)
423+
.rposition(|cell| {
424+
cell.symbol() != " " || cell.bg != bg || cell.modifier != Modifier::empty()
425+
})
412426
.unwrap_or(0);
413427
last_nonblank_column[y as usize] = x as u16;
414-
let (x_abs, y_abs) = a.pos_of(row_start + x + 1);
415428
if x < (a.area.width as usize).saturating_sub(1) {
429+
let (x_abs, y_abs) = a.pos_of(row_start + x + 1);
416430
updates.push(DrawCommand::ClearToEnd {
417431
x: x_abs,
418432
y: y_abs,

codex-rs/tui/src/diff_render.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl From<DiffSummary> for Box<dyn Renderable> {
6767
rows.push(Box::new(path));
6868
rows.push(Box::new(RtLine::from("")));
6969
rows.push(Box::new(InsetRenderable::new(
70-
Box::new(row.change),
70+
row.change,
7171
Insets::tlbr(0, 2, 0, 0),
7272
)));
7373
}

0 commit comments

Comments
 (0)