feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
//! A live status indicator that shows the *latest* log line emitted by the
|
|
|
|
|
|
//! application while the agent is processing a long‑running task.
|
|
|
|
|
|
|
|
|
|
|
|
use std::time::Duration;
|
2025-08-06 21:20:09 -07:00
|
|
|
|
use std::time::Instant;
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
|
2025-08-12 15:43:07 -07:00
|
|
|
|
use codex_core::protocol::Op;
|
2025-10-02 11:34:47 -07:00
|
|
|
|
use crossterm::event::KeyCode;
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
use ratatui::buffer::Buffer;
|
|
|
|
|
|
use ratatui::layout::Rect;
|
2025-08-25 14:38:38 -07:00
|
|
|
|
use ratatui::style::Stylize;
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
use ratatui::text::Line;
|
|
|
|
|
|
use ratatui::widgets::WidgetRef;
|
|
|
|
|
|
|
|
|
|
|
|
use crate::app_event::AppEvent;
|
2025-05-15 14:50:30 -07:00
|
|
|
|
use crate::app_event_sender::AppEventSender;
|
2025-10-07 11:34:05 -07:00
|
|
|
|
use crate::exec_cell::spinner;
|
2025-09-04 10:55:50 -07:00
|
|
|
|
use crate::key_hint;
|
2025-08-14 16:59:47 -04:00
|
|
|
|
use crate::shimmer::shimmer_spans;
|
2025-08-20 13:47:24 -07:00
|
|
|
|
use crate::tui::FrameRequester;
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
|
|
|
|
|
|
pub(crate) struct StatusIndicatorWidget {
|
2025-08-20 16:58:56 -07:00
|
|
|
|
/// Animated header text (defaults to "Working").
|
|
|
|
|
|
header: String,
|
2025-10-27 11:48:01 +00:00
|
|
|
|
show_interrupt_hint: bool,
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
|
2025-09-04 12:37:43 -07:00
|
|
|
|
elapsed_running: Duration,
|
|
|
|
|
|
last_resume_at: Instant,
|
|
|
|
|
|
is_paused: bool,
|
2025-08-12 15:43:07 -07:00
|
|
|
|
app_event_tx: AppEventSender,
|
2025-08-20 13:47:24 -07:00
|
|
|
|
frame_requester: FrameRequester,
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-06 00:06:36 +02:00
|
|
|
|
// Format elapsed seconds into a compact human-friendly form used by the status line.
|
2025-09-12 12:05:57 -04:00
|
|
|
|
// Examples: 0s, 59s, 1m 00s, 59m 59s, 1h 00m 00s, 2h 03m 09s
|
2025-09-26 22:49:59 -07:00
|
|
|
|
pub fn fmt_elapsed_compact(elapsed_secs: u64) -> String {
|
2025-09-06 00:06:36 +02:00
|
|
|
|
if elapsed_secs < 60 {
|
|
|
|
|
|
return format!("{elapsed_secs}s");
|
|
|
|
|
|
}
|
|
|
|
|
|
if elapsed_secs < 3600 {
|
|
|
|
|
|
let minutes = elapsed_secs / 60;
|
|
|
|
|
|
let seconds = elapsed_secs % 60;
|
2025-09-12 12:05:57 -04:00
|
|
|
|
return format!("{minutes}m {seconds:02}s");
|
2025-09-06 00:06:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
let hours = elapsed_secs / 3600;
|
|
|
|
|
|
let minutes = (elapsed_secs % 3600) / 60;
|
|
|
|
|
|
let seconds = elapsed_secs % 60;
|
2025-09-12 12:05:57 -04:00
|
|
|
|
format!("{hours}h {minutes:02}m {seconds:02}s")
|
2025-09-06 00:06:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
impl StatusIndicatorWidget {
|
2025-08-20 13:47:24 -07:00
|
|
|
|
pub(crate) fn new(app_event_tx: AppEventSender, frame_requester: FrameRequester) -> Self {
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
Self {
|
2025-08-20 16:58:56 -07:00
|
|
|
|
header: String::from("Working"),
|
2025-10-27 11:48:01 +00:00
|
|
|
|
show_interrupt_hint: true,
|
2025-09-04 12:37:43 -07:00
|
|
|
|
elapsed_running: Duration::ZERO,
|
|
|
|
|
|
last_resume_at: Instant::now(),
|
|
|
|
|
|
is_paused: false,
|
2025-08-04 21:23:22 -07:00
|
|
|
|
|
2025-08-12 15:43:07 -07:00
|
|
|
|
app_event_tx,
|
2025-08-20 13:47:24 -07:00
|
|
|
|
frame_requester,
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-28 09:59:19 -07:00
|
|
|
|
pub fn desired_height(&self, _width: u16) -> u16 {
|
|
|
|
|
|
1
|
2025-08-04 21:23:22 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-12 15:43:07 -07:00
|
|
|
|
pub(crate) fn interrupt(&self) {
|
|
|
|
|
|
self.app_event_tx.send(AppEvent::CodexOp(Op::Interrupt));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-20 16:58:56 -07:00
|
|
|
|
/// Update the animated header label (left of the brackets).
|
|
|
|
|
|
pub(crate) fn update_header(&mut self, header: String) {
|
2025-10-27 11:48:01 +00:00
|
|
|
|
self.header = header;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn set_interrupt_hint_visible(&mut self, visible: bool) {
|
|
|
|
|
|
self.show_interrupt_hint = visible;
|
2025-08-20 16:58:56 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-10 10:07:14 +01:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
pub(crate) fn header(&self) -> &str {
|
|
|
|
|
|
&self.header
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-27 11:48:01 +00:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
pub(crate) fn interrupt_hint_visible(&self) -> bool {
|
|
|
|
|
|
self.show_interrupt_hint
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-04 12:37:43 -07:00
|
|
|
|
pub(crate) fn pause_timer(&mut self) {
|
|
|
|
|
|
self.pause_timer_at(Instant::now());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn resume_timer(&mut self) {
|
|
|
|
|
|
self.resume_timer_at(Instant::now());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn pause_timer_at(&mut self, now: Instant) {
|
|
|
|
|
|
if self.is_paused {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
self.elapsed_running += now.saturating_duration_since(self.last_resume_at);
|
|
|
|
|
|
self.is_paused = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn resume_timer_at(&mut self, now: Instant) {
|
|
|
|
|
|
if !self.is_paused {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
self.last_resume_at = now;
|
|
|
|
|
|
self.is_paused = false;
|
|
|
|
|
|
self.frame_requester.schedule_frame();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-06 09:56:27 +05:30
|
|
|
|
fn elapsed_duration_at(&self, now: Instant) -> Duration {
|
2025-09-04 12:37:43 -07:00
|
|
|
|
let mut elapsed = self.elapsed_running;
|
|
|
|
|
|
if !self.is_paused {
|
|
|
|
|
|
elapsed += now.saturating_duration_since(self.last_resume_at);
|
|
|
|
|
|
}
|
2025-10-06 09:56:27 +05:30
|
|
|
|
elapsed
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn elapsed_seconds_at(&self, now: Instant) -> u64 {
|
|
|
|
|
|
self.elapsed_duration_at(now).as_secs()
|
2025-09-04 12:37:43 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 22:49:59 -07:00
|
|
|
|
pub fn elapsed_seconds(&self) -> u64 {
|
2025-09-04 12:37:43 -07:00
|
|
|
|
self.elapsed_seconds_at(Instant::now())
|
|
|
|
|
|
}
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl WidgetRef for StatusIndicatorWidget {
|
|
|
|
|
|
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
|
2025-08-25 14:38:38 -07:00
|
|
|
|
if area.is_empty() {
|
2025-08-04 21:23:22 -07:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-14 16:59:47 -04:00
|
|
|
|
// Schedule next animation frame.
|
2025-08-20 13:47:24 -07:00
|
|
|
|
self.frame_requester
|
2025-08-20 16:58:56 -07:00
|
|
|
|
.schedule_frame_in(Duration::from_millis(32));
|
2025-10-06 09:56:27 +05:30
|
|
|
|
let now = Instant::now();
|
|
|
|
|
|
let elapsed_duration = self.elapsed_duration_at(now);
|
|
|
|
|
|
let pretty_elapsed = fmt_elapsed_compact(elapsed_duration.as_secs());
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
|
2025-08-04 21:23:22 -07:00
|
|
|
|
// Plain rendering: no borders or padding so the live cell is visually indistinguishable from terminal scrollback.
|
2025-10-06 09:56:27 +05:30
|
|
|
|
let mut spans = Vec::with_capacity(5);
|
2025-10-07 11:34:05 -07:00
|
|
|
|
spans.push(spinner(Some(self.last_resume_at)));
|
|
|
|
|
|
spans.push(" ".into());
|
2025-08-25 14:38:38 -07:00
|
|
|
|
spans.extend(shimmer_spans(&self.header));
|
2025-10-27 11:48:01 +00:00
|
|
|
|
spans.push(" ".into());
|
|
|
|
|
|
if self.show_interrupt_hint {
|
|
|
|
|
|
spans.extend(vec![
|
|
|
|
|
|
format!("({pretty_elapsed} • ").dim(),
|
|
|
|
|
|
key_hint::plain(KeyCode::Esc).into(),
|
|
|
|
|
|
" to interrupt)".dim(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
spans.push(format!("({pretty_elapsed})").dim());
|
|
|
|
|
|
}
|
2025-08-25 14:38:38 -07:00
|
|
|
|
|
2025-10-28 09:59:19 -07:00
|
|
|
|
Line::from(spans).render_ref(area, buf);
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-03 11:51:33 -07:00
|
|
|
|
|
2025-08-04 21:23:22 -07:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod tests {
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
use crate::app_event::AppEvent;
|
|
|
|
|
|
use crate::app_event_sender::AppEventSender;
|
2025-08-25 14:38:38 -07:00
|
|
|
|
use ratatui::Terminal;
|
|
|
|
|
|
use ratatui::backend::TestBackend;
|
2025-09-04 12:37:43 -07:00
|
|
|
|
use std::time::Duration;
|
|
|
|
|
|
use std::time::Instant;
|
2025-08-20 10:11:09 -07:00
|
|
|
|
use tokio::sync::mpsc::unbounded_channel;
|
2025-08-04 21:23:22 -07:00
|
|
|
|
|
2025-09-06 00:06:36 +02:00
|
|
|
|
use pretty_assertions::assert_eq;
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn fmt_elapsed_compact_formats_seconds_minutes_hours() {
|
|
|
|
|
|
assert_eq!(fmt_elapsed_compact(0), "0s");
|
|
|
|
|
|
assert_eq!(fmt_elapsed_compact(1), "1s");
|
|
|
|
|
|
assert_eq!(fmt_elapsed_compact(59), "59s");
|
2025-09-12 12:05:57 -04:00
|
|
|
|
assert_eq!(fmt_elapsed_compact(60), "1m 00s");
|
|
|
|
|
|
assert_eq!(fmt_elapsed_compact(61), "1m 01s");
|
|
|
|
|
|
assert_eq!(fmt_elapsed_compact(3 * 60 + 5), "3m 05s");
|
|
|
|
|
|
assert_eq!(fmt_elapsed_compact(59 * 60 + 59), "59m 59s");
|
|
|
|
|
|
assert_eq!(fmt_elapsed_compact(3600), "1h 00m 00s");
|
|
|
|
|
|
assert_eq!(fmt_elapsed_compact(3600 + 60 + 1), "1h 01m 01s");
|
|
|
|
|
|
assert_eq!(fmt_elapsed_compact(25 * 3600 + 2 * 60 + 3), "25h 02m 03s");
|
2025-09-06 00:06:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-04 21:23:22 -07:00
|
|
|
|
#[test]
|
2025-08-25 14:38:38 -07:00
|
|
|
|
fn renders_with_working_header() {
|
2025-08-20 10:11:09 -07:00
|
|
|
|
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
2025-08-04 21:23:22 -07:00
|
|
|
|
let tx = AppEventSender::new(tx_raw);
|
2025-08-25 14:38:38 -07:00
|
|
|
|
let w = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy());
|
|
|
|
|
|
|
|
|
|
|
|
// Render into a fixed-size test terminal and snapshot the backend.
|
|
|
|
|
|
let mut terminal = Terminal::new(TestBackend::new(80, 2)).expect("terminal");
|
|
|
|
|
|
terminal
|
|
|
|
|
|
.draw(|f| w.render_ref(f.area(), f.buffer_mut()))
|
|
|
|
|
|
.expect("draw");
|
2025-09-04 10:55:50 -07:00
|
|
|
|
insta::assert_snapshot!(terminal.backend());
|
2025-08-04 21:23:22 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
2025-08-25 14:38:38 -07:00
|
|
|
|
fn renders_truncated() {
|
2025-08-20 10:11:09 -07:00
|
|
|
|
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
2025-08-04 21:23:22 -07:00
|
|
|
|
let tx = AppEventSender::new(tx_raw);
|
2025-08-25 14:38:38 -07:00
|
|
|
|
let w = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy());
|
|
|
|
|
|
|
|
|
|
|
|
// Render into a fixed-size test terminal and snapshot the backend.
|
|
|
|
|
|
let mut terminal = Terminal::new(TestBackend::new(20, 2)).expect("terminal");
|
|
|
|
|
|
terminal
|
|
|
|
|
|
.draw(|f| w.render_ref(f.area(), f.buffer_mut()))
|
|
|
|
|
|
.expect("draw");
|
2025-09-04 10:55:50 -07:00
|
|
|
|
insta::assert_snapshot!(terminal.backend());
|
2025-08-04 21:23:22 -07:00
|
|
|
|
}
|
2025-08-07 01:45:04 -07:00
|
|
|
|
|
2025-09-04 12:37:43 -07:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn timer_pauses_when_requested() {
|
|
|
|
|
|
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
|
|
|
|
|
let tx = AppEventSender::new(tx_raw);
|
|
|
|
|
|
let mut widget = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy());
|
|
|
|
|
|
|
|
|
|
|
|
let baseline = Instant::now();
|
|
|
|
|
|
widget.last_resume_at = baseline;
|
|
|
|
|
|
|
|
|
|
|
|
let before_pause = widget.elapsed_seconds_at(baseline + Duration::from_secs(5));
|
|
|
|
|
|
assert_eq!(before_pause, 5);
|
|
|
|
|
|
|
|
|
|
|
|
widget.pause_timer_at(baseline + Duration::from_secs(5));
|
|
|
|
|
|
let paused_elapsed = widget.elapsed_seconds_at(baseline + Duration::from_secs(10));
|
|
|
|
|
|
assert_eq!(paused_elapsed, before_pause);
|
|
|
|
|
|
|
|
|
|
|
|
widget.resume_timer_at(baseline + Duration::from_secs(10));
|
|
|
|
|
|
let after_resume = widget.elapsed_seconds_at(baseline + Duration::from_secs(13));
|
|
|
|
|
|
assert_eq!(after_resume, before_pause + 3);
|
|
|
|
|
|
}
|
2025-08-04 21:23:22 -07:00
|
|
|
|
}
|