mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
agentydragon(tasks): implement TUI integration for /inspect-env
This commit is contained in:
@@ -10,7 +10,7 @@ last_updated = "2025-06-25T04:45:29Z"
|
||||
|
||||
## Status
|
||||
|
||||
**General Status**: Not started
|
||||
**General Status**: In progress
|
||||
**Summary**: Follow-up to Task 10; add slash-command and TUI bindings for `inspect-env`.
|
||||
|
||||
## Goal
|
||||
@@ -27,11 +27,15 @@ Add an `/inspect-env` slash-command in the TUI that invokes the existing `codex
|
||||
|
||||
## Implementation
|
||||
|
||||
**How it was implemented**
|
||||
*(Not implemented yet)*
|
||||
**High-level approach**
|
||||
- Extend `SlashCommand` enum with `InspectEnv` and provide user-visible description.
|
||||
- Add `InlineInspectEnv` variant to `AppEvent` enum to represent inline slash-command invocation.
|
||||
- Update dispatch logic in `App::run` to spawn a background thread on `InlineInspectEnv` that runs `codex inspect-env`, reads its stdout line-by-line, and sends each line as `AppEvent::LatestLog`, then triggers a redraw.
|
||||
- Wire up `/inspect-env` to dispatch `InlineInspectEnv` in the slash-command handling.
|
||||
- Add unit tests in the TUI crate to verify `built_in_slash_commands()` includes `inspect-env` mapping and description.
|
||||
|
||||
**How it works**
|
||||
*(Not implemented yet)*
|
||||
When the user enters `/inspect-env`, the TUI parser recognizes the command and emits `AppEvent::InlineInspectEnv`. The main event loop handles this event by spawning a thread that invokes the external `codex inspect-env` command, captures its output line-by-line, and forwards each line into the TUI log pane via `AppEvent::LatestLog`. A redraw is scheduled once the inspection completes.
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@ use std::sync::mpsc::channel;
|
||||
use codex_core::ResponseItem;
|
||||
use uuid::Uuid;
|
||||
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::process::{Command, Stdio};
|
||||
use std::thread;
|
||||
|
||||
/// Top-level application state: which full-screen view is currently active.
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
enum AppState<'a> {
|
||||
@@ -309,6 +313,32 @@ impl<'a> App<'a> {
|
||||
}
|
||||
self.app_event_tx.send(AppEvent::Redraw);
|
||||
}
|
||||
AppEvent::InlineInspectEnv(_raw) => {
|
||||
let tx = self.app_event_tx.clone();
|
||||
thread::spawn(move || {
|
||||
match Command::new("codex")
|
||||
.arg("inspect-env")
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(mut child) => {
|
||||
if let Some(stdout) = child.stdout.take() {
|
||||
let reader = BufReader::new(stdout);
|
||||
for line in reader.lines().flatten() {
|
||||
let _ = tx.send(AppEvent::LatestLog(line));
|
||||
}
|
||||
}
|
||||
let _ = child.wait();
|
||||
}
|
||||
Err(err) => {
|
||||
let _ = tx.send(AppEvent::LatestLog(
|
||||
format!("Failed to spawn inspect-env: {err}")
|
||||
));
|
||||
}
|
||||
}
|
||||
let _ = tx.send(AppEvent::Redraw);
|
||||
});
|
||||
}
|
||||
AppEvent::MountAdd { host, container, mode } => {
|
||||
if let Err(err) = do_mount_add(&mut self.config, &host, &container, &mode) {
|
||||
tracing::error!("mount-add failed: {err}");
|
||||
@@ -401,6 +431,10 @@ impl<'a> App<'a> {
|
||||
self.app_event_tx.send(AppEvent::Redraw);
|
||||
}
|
||||
}
|
||||
SlashCommand::InspectEnv => {
|
||||
let _ = self.app_event_tx.send(AppEvent::InlineInspectEnv(String::new()));
|
||||
let _ = self.app_event_tx.send(AppEvent::Redraw);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ pub(crate) enum AppEvent {
|
||||
InlineMountAdd(String),
|
||||
/// Inline mount-remove DSL: raw argument string (`container=...`).
|
||||
InlineMountRemove(String),
|
||||
/// Inline inspect-env DSL: raw argument string (unused).
|
||||
InlineInspectEnv(String),
|
||||
/// Perform mount-add: create symlink and update sandbox policy.
|
||||
MountAdd {
|
||||
host: std::path::PathBuf,
|
||||
|
||||
@@ -21,6 +21,8 @@ pub enum SlashCommand {
|
||||
MountAdd,
|
||||
/// Remove a dynamic mount by container path.
|
||||
MountRemove,
|
||||
/// Inspect sandbox and container environment (mounts, permissions, network).
|
||||
InspectEnv,
|
||||
}
|
||||
|
||||
impl SlashCommand {
|
||||
@@ -35,6 +37,7 @@ impl SlashCommand {
|
||||
SlashCommand::Quit => "Exit the application.",
|
||||
SlashCommand::MountAdd => "Add a mount: host path → container path.",
|
||||
SlashCommand::MountRemove => "Remove a mount by container path.",
|
||||
SlashCommand::InspectEnv => "Inspect sandbox and container environment (mounts, permissions, network)",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,3 +52,20 @@ impl SlashCommand {
|
||||
pub fn built_in_slash_commands() -> HashMap<&'static str, SlashCommand> {
|
||||
SlashCommand::iter().map(|c| (c.command(), c)).collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn built_in_includes_inspect_env() {
|
||||
let commands = built_in_slash_commands();
|
||||
assert_eq!(commands.get("inspect-env"), Some(&SlashCommand::InspectEnv));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inspect_env_description_contains_keyword() {
|
||||
let desc = SlashCommand::InspectEnv.description();
|
||||
assert!(desc.contains("sandbox"), "description was: {}", desc);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user