mirror of
https://github.com/openai/codex.git
synced 2026-10-19 16:17:49 +00:00
Remove unused Rust helpers (#34345)
## What changed - Remove unused APIs and test helpers across the Rust workspace. - Route Linux sandbox test setup through the shared exec request path. - Drop dependencies that became unnecessary after the cleanup. GitOrigin-RevId: 48fd9b2b1575bad7add0819786b4d8ec88d8486f
This commit is contained in:
Generated
-3
@@ -4405,8 +4405,6 @@ dependencies = [
|
||||
name = "codex-utils-sandbox-summary"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"codex-core",
|
||||
"codex-model-provider-info",
|
||||
"codex-protocol",
|
||||
"codex-utils-absolute-path",
|
||||
"pretty_assertions",
|
||||
@@ -8911,7 +8909,6 @@ dependencies = [
|
||||
"os_info",
|
||||
"pretty_assertions",
|
||||
"rmcp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shlex",
|
||||
"tokio",
|
||||
|
||||
@@ -198,13 +198,6 @@ pub async fn bootstrap(options: BootstrapOptions) -> Result<BootstrapOutput> {
|
||||
Daemon::from_environment()?.bootstrap(options).await
|
||||
}
|
||||
|
||||
pub async fn ensure_remote_control_started() -> Result<RemoteControlStartOutput> {
|
||||
ensure_supported_platform()?;
|
||||
Daemon::from_environment()?
|
||||
.ensure_remote_control_started()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn ensure_remote_control_ready() -> Result<RemoteControlReadyOutput> {
|
||||
ensure_supported_platform()?;
|
||||
Daemon::from_environment()?
|
||||
|
||||
@@ -25,7 +25,6 @@ use crate::protocol::v2::ThreadItem;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::parse_command::ParsedCommand;
|
||||
use codex_protocol::protocol::ApplyPatchApprovalRequestEvent;
|
||||
use codex_protocol::protocol::ExecApprovalRequestEvent;
|
||||
use codex_protocol::protocol::ExecCommandBeginEvent;
|
||||
use codex_protocol::protocol::ExecCommandEndEvent;
|
||||
use codex_protocol::protocol::FileChange;
|
||||
@@ -76,28 +75,6 @@ pub fn build_file_change_end_item(payload: &PatchApplyEndEvent) -> ThreadItem {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_command_execution_approval_request_item(
|
||||
payload: &ExecApprovalRequestEvent,
|
||||
) -> ThreadItem {
|
||||
ThreadItem::CommandExecution {
|
||||
id: payload.call_id.clone(),
|
||||
command: shlex_join(&payload.command),
|
||||
cwd: payload.cwd.clone().into(),
|
||||
process_id: None,
|
||||
source: CommandExecutionSource::Agent,
|
||||
status: CommandExecutionStatus::InProgress,
|
||||
command_actions: payload
|
||||
.parsed_cmd
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|parsed| CommandAction::from_core_with_cwd(parsed, &payload.cwd))
|
||||
.collect(),
|
||||
aggregated_output: None,
|
||||
exit_code: None,
|
||||
duration_ms: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_command_execution_begin_item(payload: &ExecCommandBeginEvent) -> ThreadItem {
|
||||
let command_actions = command_actions_for_path_uri(&payload.parsed_cmd, &payload.cwd);
|
||||
ThreadItem::CommandExecution {
|
||||
|
||||
@@ -31,7 +31,6 @@ use codex_app_server_protocol::ConfigReadParams;
|
||||
use codex_app_server_protocol::ConfigValueWriteParams;
|
||||
use codex_app_server_protocol::ConsumeAccountRateLimitResetCreditParams;
|
||||
use codex_app_server_protocol::ExperimentalFeatureListParams;
|
||||
use codex_app_server_protocol::FeedbackUploadParams;
|
||||
use codex_app_server_protocol::FsCopyParams;
|
||||
use codex_app_server_protocol::FsCreateDirectoryParams;
|
||||
use codex_app_server_protocol::FsGetMetadataParams;
|
||||
@@ -71,9 +70,7 @@ use codex_app_server_protocol::PluginReadParams;
|
||||
use codex_app_server_protocol::PluginSkillReadParams;
|
||||
use codex_app_server_protocol::PluginUninstallParams;
|
||||
use codex_app_server_protocol::ProcessKillParams;
|
||||
use codex_app_server_protocol::ProcessResizePtyParams;
|
||||
use codex_app_server_protocol::ProcessSpawnParams;
|
||||
use codex_app_server_protocol::ProcessWriteStdinParams;
|
||||
use codex_app_server_protocol::RemoteControlClientsListParams;
|
||||
use codex_app_server_protocol::RemoteControlClientsRevokeParams;
|
||||
use codex_app_server_protocol::RemoteControlPairingStartParams;
|
||||
@@ -147,7 +144,6 @@ pub struct TestAppServer {
|
||||
pending_messages: VecDeque<JSONRPCMessage>,
|
||||
auto_env: Option<TestEnv>,
|
||||
json_logs: JsonLogCapture,
|
||||
codex_home: PathBuf,
|
||||
// Fields drop in declaration order. Tear down the delayed child before
|
||||
// removing an owned CODEX_HOME that may still be its cwd on Windows.
|
||||
_delayed_exec_server: Option<(LocalWebsocketExecServer, WebsocketDelayInterposer)>,
|
||||
@@ -205,11 +201,6 @@ impl TestAppServer {
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the effective CODEX_HOME used by the child app-server.
|
||||
pub fn codex_home(&self) -> &Path {
|
||||
&self.codex_home
|
||||
}
|
||||
|
||||
/// Waits for a JSON stderr event whose structured `event.name` field matches.
|
||||
pub async fn wait_for_json_log_event(
|
||||
&self,
|
||||
@@ -218,20 +209,6 @@ impl TestAppServer {
|
||||
self.json_logs.wait_for_event(event_name).await
|
||||
}
|
||||
|
||||
/// Waits for the requested number of JSON stderr events with the same `event.name` field.
|
||||
pub async fn wait_for_json_log_events(
|
||||
&self,
|
||||
event_name: &str,
|
||||
count: usize,
|
||||
) -> anyhow::Result<Vec<serde_json::Value>> {
|
||||
self.json_logs.wait_for_events(event_name, count).await
|
||||
}
|
||||
|
||||
/// Returns every stderr line parsed and validated as a JSON log event.
|
||||
pub fn json_log_events(&self) -> anyhow::Result<Vec<serde_json::Value>> {
|
||||
self.json_logs.events()
|
||||
}
|
||||
|
||||
async fn new_with_program_env_and_args(
|
||||
codex_home: &Path,
|
||||
program: &Path,
|
||||
@@ -300,7 +277,6 @@ impl TestAppServer {
|
||||
pending_messages: VecDeque::new(),
|
||||
auto_env: None,
|
||||
json_logs,
|
||||
codex_home: codex_home.to_path_buf(),
|
||||
_delayed_exec_server: None,
|
||||
_owned_codex_home: None,
|
||||
})
|
||||
@@ -461,15 +437,6 @@ impl TestAppServer {
|
||||
.await
|
||||
}
|
||||
|
||||
/// Send a `feedback/upload` JSON-RPC request.
|
||||
pub async fn send_feedback_upload_request(
|
||||
&mut self,
|
||||
params: FeedbackUploadParams,
|
||||
) -> anyhow::Result<i64> {
|
||||
let params = Some(serde_json::to_value(params)?);
|
||||
self.send_request("feedback/upload", params).await
|
||||
}
|
||||
|
||||
/// Send a `thread/start` JSON-RPC request.
|
||||
pub async fn send_thread_start_request(
|
||||
&mut self,
|
||||
@@ -1047,24 +1014,6 @@ impl TestAppServer {
|
||||
self.send_request("process/spawn", params).await
|
||||
}
|
||||
|
||||
/// Send a `process/writeStdin` JSON-RPC request (v2).
|
||||
pub async fn send_process_write_stdin_request(
|
||||
&mut self,
|
||||
params: ProcessWriteStdinParams,
|
||||
) -> anyhow::Result<i64> {
|
||||
let params = Some(serde_json::to_value(params)?);
|
||||
self.send_request("process/writeStdin", params).await
|
||||
}
|
||||
|
||||
/// Send a `process/resizePty` JSON-RPC request (v2).
|
||||
pub async fn send_process_resize_pty_request(
|
||||
&mut self,
|
||||
params: ProcessResizePtyParams,
|
||||
) -> anyhow::Result<i64> {
|
||||
let params = Some(serde_json::to_value(params)?);
|
||||
self.send_request("process/resizePty", params).await
|
||||
}
|
||||
|
||||
/// Send a `process/kill` JSON-RPC request (v2).
|
||||
pub async fn send_process_kill_request(
|
||||
&mut self,
|
||||
|
||||
@@ -272,10 +272,6 @@ pub struct NetworkDomainPermissionsToml {
|
||||
}
|
||||
|
||||
impl NetworkDomainPermissionsToml {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.entries.is_empty()
|
||||
}
|
||||
|
||||
pub fn allowed_domains(&self) -> Option<Vec<String>> {
|
||||
let allowed_domains: Vec<String> = self
|
||||
.entries
|
||||
@@ -321,10 +317,6 @@ pub struct NetworkUnixSocketPermissionsToml {
|
||||
}
|
||||
|
||||
impl NetworkUnixSocketPermissionsToml {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.entries.is_empty()
|
||||
}
|
||||
|
||||
pub fn allow_unix_sockets(&self) -> Vec<String> {
|
||||
self.entries
|
||||
.iter()
|
||||
|
||||
@@ -250,10 +250,6 @@ pub struct NetworkDomainPermissionsToml {
|
||||
}
|
||||
|
||||
impl NetworkDomainPermissionsToml {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.entries.is_empty()
|
||||
}
|
||||
|
||||
pub fn allowed_domains(&self) -> Option<Vec<String>> {
|
||||
let allowed_domains: Vec<String> = self
|
||||
.entries
|
||||
@@ -301,10 +297,6 @@ pub struct NetworkUnixSocketPermissionsToml {
|
||||
}
|
||||
|
||||
impl NetworkUnixSocketPermissionsToml {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.entries.is_empty()
|
||||
}
|
||||
|
||||
pub fn allow_unix_sockets(&self) -> Vec<String> {
|
||||
self.entries
|
||||
.iter()
|
||||
|
||||
@@ -75,10 +75,6 @@ impl ThreadConfigLoadError {
|
||||
pub fn code(&self) -> ThreadConfigLoadErrorCode {
|
||||
self.code
|
||||
}
|
||||
|
||||
pub fn status_code(&self) -> Option<u16> {
|
||||
self.status_code
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads typed config sources for a new thread.
|
||||
|
||||
@@ -190,18 +190,6 @@ pub enum UriBasedFileOpener {
|
||||
None,
|
||||
}
|
||||
|
||||
impl UriBasedFileOpener {
|
||||
pub fn get_scheme(&self) -> Option<&str> {
|
||||
match self {
|
||||
UriBasedFileOpener::VsCode => Some("vscode"),
|
||||
UriBasedFileOpener::VsCodeInsiders => Some("vscode-insiders"),
|
||||
UriBasedFileOpener::Windsurf => Some("windsurf"),
|
||||
UriBasedFileOpener::Cursor => Some("cursor"),
|
||||
UriBasedFileOpener::None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Settings that govern if and what will be written to `~/.codex/history.jsonl`.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||
#[serde(default)]
|
||||
|
||||
@@ -739,16 +739,6 @@ fn apply_blocking_to_resolved_file(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Persist edits asynchronously by offloading the blocking writer.
|
||||
///
|
||||
pub async fn apply(codex_home: &Path, edits: Vec<ConfigEdit>) -> anyhow::Result<()> {
|
||||
let codex_home = codex_home.to_path_buf();
|
||||
let config_path = codex_home.join(CONFIG_TOML_FILE);
|
||||
task::spawn_blocking(move || apply_blocking_to_resolved_file(&config_path, &edits))
|
||||
.await
|
||||
.context("config persistence task panicked")?
|
||||
}
|
||||
|
||||
/// Fluent builder to batch config edits and apply them atomically.
|
||||
#[derive(Default)]
|
||||
pub struct ConfigEditsBuilder {
|
||||
@@ -790,12 +780,6 @@ impl ConfigEditsBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_personality(mut self, personality: Option<Personality>) -> Self {
|
||||
self.edits
|
||||
.push(ConfigEdit::SetModelPersonality { personality });
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_hide_full_access_warning(mut self, acknowledged: bool) -> Self {
|
||||
self.edits
|
||||
.push(ConfigEdit::SetNoticeHideFullAccessWarning(acknowledged));
|
||||
@@ -814,37 +798,6 @@ impl ConfigEditsBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_hide_model_migration_prompt(mut self, model: &str, acknowledged: bool) -> Self {
|
||||
self.edits
|
||||
.push(ConfigEdit::SetNoticeHideModelMigrationPrompt(
|
||||
model.to_string(),
|
||||
acknowledged,
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_hide_external_config_migration_prompt_home(mut self, acknowledged: bool) -> Self {
|
||||
self.edits
|
||||
.push(ConfigEdit::SetNoticeHideExternalConfigMigrationPromptHome(
|
||||
acknowledged,
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_hide_external_config_migration_prompt_project(
|
||||
mut self,
|
||||
project: &str,
|
||||
acknowledged: bool,
|
||||
) -> Self {
|
||||
self.edits.push(
|
||||
ConfigEdit::SetNoticeHideExternalConfigMigrationPromptProject(
|
||||
project.to_string(),
|
||||
acknowledged,
|
||||
),
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn record_model_migration_seen(mut self, from: &str, to: &str) -> Self {
|
||||
self.edits.push(ConfigEdit::RecordModelMigrationSeen {
|
||||
from: from.to_string(),
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
use crate::spawn::SpawnChildRequest;
|
||||
use crate::spawn::StdioPolicy;
|
||||
use crate::spawn::spawn_child_async;
|
||||
use codex_network_proxy::NetworkProxy;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0;
|
||||
use codex_sandboxing::landlock::allow_network_for_proxy;
|
||||
use codex_sandboxing::landlock::create_linux_sandbox_command_args_for_permission_profile;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use tokio::process::Child;
|
||||
|
||||
/// Spawn a shell tool command under the Linux sandbox helper
|
||||
/// (codex-linux-sandbox), which defaults to bubblewrap for filesystem
|
||||
/// isolation plus seccomp for network restrictions.
|
||||
///
|
||||
/// Unlike macOS Seatbelt where we directly embed the policy text, the Linux
|
||||
/// helper is a separate executable. We pass the canonical permission profile
|
||||
/// as JSON and let the helper derive the runtime filesystem/network policies.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn spawn_command_under_linux_sandbox<P>(
|
||||
codex_linux_sandbox_exe: P,
|
||||
command: Vec<String>,
|
||||
command_cwd: AbsolutePathBuf,
|
||||
permission_profile: &PermissionProfile,
|
||||
sandbox_policy_cwd: &AbsolutePathBuf,
|
||||
use_legacy_landlock: bool,
|
||||
stdio_policy: StdioPolicy,
|
||||
network: Option<&NetworkProxy>,
|
||||
env: HashMap<String, String>,
|
||||
) -> std::io::Result<Child>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let network_sandbox_policy = permission_profile.network_sandbox_policy();
|
||||
let args = create_linux_sandbox_command_args_for_permission_profile(
|
||||
command,
|
||||
command_cwd.as_path(),
|
||||
permission_profile,
|
||||
sandbox_policy_cwd,
|
||||
use_legacy_landlock,
|
||||
allow_network_for_proxy(/*enforce_managed_network*/ false),
|
||||
);
|
||||
let codex_linux_sandbox_exe = codex_linux_sandbox_exe.as_ref();
|
||||
// Preserve the helper alias when we already have it; otherwise force argv0
|
||||
// so arg0 dispatch still reaches the Linux sandbox path.
|
||||
let arg0 = if codex_linux_sandbox_exe
|
||||
.file_name()
|
||||
.and_then(|name| name.to_str())
|
||||
== Some(CODEX_LINUX_SANDBOX_ARG0)
|
||||
{
|
||||
// Old bubblewrap builds without `--argv0` need a real helper path whose
|
||||
// basename still dispatches to the Linux sandbox entrypoint.
|
||||
codex_linux_sandbox_exe.to_string_lossy().into_owned()
|
||||
} else {
|
||||
CODEX_LINUX_SANDBOX_ARG0.to_string()
|
||||
};
|
||||
spawn_child_async(SpawnChildRequest {
|
||||
program: codex_linux_sandbox_exe.to_path_buf(),
|
||||
args,
|
||||
arg0: Some(&arg0),
|
||||
cwd: command_cwd,
|
||||
network_sandbox_policy,
|
||||
network,
|
||||
stdio_policy,
|
||||
env,
|
||||
})
|
||||
.await
|
||||
}
|
||||
@@ -53,8 +53,6 @@ mod guardian;
|
||||
mod hook_runtime;
|
||||
mod image_preparation;
|
||||
mod installation_id;
|
||||
pub(crate) mod landlock;
|
||||
pub use landlock::spawn_command_under_linux_sandbox;
|
||||
pub(crate) mod mcp;
|
||||
mod mcp_skill_dependencies;
|
||||
mod mcp_tool_approval_templates;
|
||||
@@ -120,7 +118,6 @@ pub use thread_manager::build_models_manager;
|
||||
pub use thread_manager::local_agent_graph_store_from_state_db;
|
||||
pub use thread_manager::thread_store_from_config;
|
||||
pub use web_search::web_search_action_detail;
|
||||
pub use web_search::web_search_detail;
|
||||
pub use windows_sandbox_read_grants::grant_read_root_non_elevated;
|
||||
#[deprecated(note = "use ThreadManager")]
|
||||
pub type ConversationManager = ThreadManager;
|
||||
|
||||
@@ -94,12 +94,6 @@ pub fn build_provider(
|
||||
})
|
||||
}
|
||||
|
||||
/// Filter predicate for exporting only Codex-owned events via OTEL.
|
||||
/// Keeps events that originated from codex_otel module
|
||||
pub fn codex_export_filter(meta: &tracing::Metadata<'_>) -> bool {
|
||||
meta.target().starts_with("codex_otel")
|
||||
}
|
||||
|
||||
pub fn record_process_start(otel: Option<&OtelProvider>, originator: &str) {
|
||||
let Some(metrics) = otel.and_then(OtelProvider::metrics) else {
|
||||
return;
|
||||
|
||||
@@ -101,22 +101,6 @@ pub fn thread_manager_with_models_provider_and_home(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn thread_manager_with_models_provider_home_and_state(
|
||||
auth: CodexAuth,
|
||||
provider: ModelProviderInfo,
|
||||
codex_home: PathBuf,
|
||||
environment_manager: Arc<EnvironmentManager>,
|
||||
state_db: Option<crate::StateDbHandle>,
|
||||
) -> ThreadManager {
|
||||
ThreadManager::with_models_provider_home_and_state_for_tests(
|
||||
auth,
|
||||
provider,
|
||||
codex_home,
|
||||
environment_manager,
|
||||
state_db,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn start_thread_with_user_shell_override(
|
||||
thread_manager: &ThreadManager,
|
||||
config: Config,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
use rand::Rng;
|
||||
@@ -20,6 +18,9 @@ const BACKOFF_FACTOR: f64 = 2.0;
|
||||
/// Example:
|
||||
///
|
||||
/// ```rust
|
||||
/// let provider_id = "openai";
|
||||
/// let request_id = "req-123";
|
||||
///
|
||||
/// codex_core::feedback_tags!(model = "gpt-5", cached = true);
|
||||
/// codex_core::feedback_tags!(provider = provider_id, request_id = request_id);
|
||||
/// ```
|
||||
@@ -97,14 +98,6 @@ pub(crate) fn error_or_panic(message: impl std::string::ToString) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_path(base: &Path, path: &PathBuf) -> PathBuf {
|
||||
if path.is_absolute() {
|
||||
path.clone()
|
||||
} else {
|
||||
base.join(path)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trim a thread name and return `None` if it is empty after trimming.
|
||||
pub fn normalize_thread_name(name: &str) -> Option<String> {
|
||||
let trimmed = name.trim();
|
||||
|
||||
@@ -28,12 +28,3 @@ pub fn web_search_action_detail(action: &WebSearchAction) -> String {
|
||||
WebSearchAction::Other => String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn web_search_detail(action: Option<&WebSearchAction>, query: &str) -> String {
|
||||
let detail = action.map(web_search_action_detail).unwrap_or_default();
|
||||
if detail.is_empty() {
|
||||
query.to_string()
|
||||
} else {
|
||||
detail
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,6 @@ use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
|
||||
/// Kill switch for the elevated sandbox NUX on Windows.
|
||||
///
|
||||
/// When false, revert to the previous sandbox NUX, which only
|
||||
/// prompts users to enable the legacy sandbox feature.
|
||||
pub const ELEVATED_SANDBOX_NUX_ENABLED: bool = true;
|
||||
|
||||
pub trait WindowsSandboxLevelExt {
|
||||
fn from_config(config: &Config) -> WindowsSandboxLevel;
|
||||
fn from_features(features: &Features) -> WindowsSandboxLevel;
|
||||
@@ -48,14 +42,6 @@ impl WindowsSandboxLevelExt for WindowsSandboxLevel {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn windows_sandbox_level_from_config(config: &Config) -> WindowsSandboxLevel {
|
||||
WindowsSandboxLevel::from_config(config)
|
||||
}
|
||||
|
||||
pub fn windows_sandbox_level_from_features(features: &Features) -> WindowsSandboxLevel {
|
||||
WindowsSandboxLevel::from_features(features)
|
||||
}
|
||||
|
||||
pub fn resolve_windows_sandbox_mode(cfg: &ConfigToml) -> Option<WindowsSandboxModeToml> {
|
||||
cfg.windows
|
||||
.as_ref()
|
||||
@@ -112,38 +98,6 @@ pub fn sandbox_setup_is_complete(_codex_home: &Path) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn elevated_setup_failure_details(err: &anyhow::Error) -> Option<(String, String)> {
|
||||
let failure = codex_windows_sandbox::extract_setup_failure(err)?;
|
||||
let code = failure.code.as_str().to_string();
|
||||
let message = codex_windows_sandbox::sanitize_setup_metric_tag_value(&failure.message);
|
||||
Some((code, message))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn elevated_setup_failure_details(_err: &anyhow::Error) -> Option<(String, String)> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn elevated_setup_failure_metric_name(err: &anyhow::Error) -> &'static str {
|
||||
if codex_windows_sandbox::extract_setup_failure(err).is_some_and(|failure| {
|
||||
matches!(
|
||||
failure.code,
|
||||
codex_windows_sandbox::SetupErrorCode::OrchestratorHelperLaunchCanceled
|
||||
)
|
||||
}) {
|
||||
"codex.windows_sandbox.elevated_setup_canceled"
|
||||
} else {
|
||||
"codex.windows_sandbox.elevated_setup_failure"
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn elevated_setup_failure_metric_name(_err: &anyhow::Error) -> &'static str {
|
||||
panic!("elevated_setup_failure_metric_name is only supported on Windows")
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn run_elevated_setup(
|
||||
permission_profile: &PermissionProfile,
|
||||
@@ -398,9 +352,11 @@ fn emit_windows_sandbox_setup_failure_metrics(
|
||||
let mut failure_tags: Vec<(&str, &str)> = vec![("originator", originator_tag)];
|
||||
let mut code_tag: Option<String> = None;
|
||||
let mut message_tag: Option<String> = None;
|
||||
if let Some((code, message)) = elevated_setup_failure_details(_err) {
|
||||
code_tag = Some(code);
|
||||
message_tag = Some(message);
|
||||
if let Some(failure) = codex_windows_sandbox::extract_setup_failure(_err) {
|
||||
code_tag = Some(failure.code.as_str().to_string());
|
||||
message_tag = Some(codex_windows_sandbox::sanitize_setup_metric_tag_value(
|
||||
&failure.message,
|
||||
));
|
||||
}
|
||||
if let Some(code) = code_tag.as_deref() {
|
||||
failure_tags.push(("code", code));
|
||||
@@ -408,11 +364,18 @@ fn emit_windows_sandbox_setup_failure_metrics(
|
||||
if let Some(message) = message_tag.as_deref() {
|
||||
failure_tags.push(("message", message));
|
||||
}
|
||||
let _ = metrics.counter(
|
||||
elevated_setup_failure_metric_name(_err),
|
||||
/*inc*/ 1,
|
||||
&failure_tags,
|
||||
);
|
||||
let metric_name =
|
||||
if codex_windows_sandbox::extract_setup_failure(_err).is_some_and(|failure| {
|
||||
matches!(
|
||||
failure.code,
|
||||
codex_windows_sandbox::SetupErrorCode::OrchestratorHelperLaunchCanceled
|
||||
)
|
||||
}) {
|
||||
"codex.windows_sandbox.elevated_setup_canceled"
|
||||
} else {
|
||||
"codex.windows_sandbox.elevated_setup_failure"
|
||||
};
|
||||
let _ = metrics.counter(metric_name, /*inc*/ 1, &failure_tags);
|
||||
}
|
||||
} else {
|
||||
let _ = metrics.counter(
|
||||
|
||||
@@ -929,21 +929,6 @@ pub fn ev_custom_tool_call_with_namespace(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ev_local_shell_call(call_id: &str, status: &str, command: Vec<&str>) -> Value {
|
||||
serde_json::json!({
|
||||
"type": "response.output_item.done",
|
||||
"item": {
|
||||
"type": "local_shell_call",
|
||||
"call_id": call_id,
|
||||
"status": status,
|
||||
"action": {
|
||||
"type": "exec",
|
||||
"command": command,
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Convenience: SSE event for an `apply_patch` custom tool call with raw patch
|
||||
/// text. This mirrors the payload produced by the Responses API when the model
|
||||
/// invokes `apply_patch` directly.
|
||||
@@ -1064,27 +1049,6 @@ pub async fn mount_sse_once(server: &MockServer, body: String) -> ResponseMock {
|
||||
response_mock
|
||||
}
|
||||
|
||||
pub async fn mount_compact_json_once_match<M>(
|
||||
server: &MockServer,
|
||||
matcher: M,
|
||||
body: serde_json::Value,
|
||||
) -> ResponseMock
|
||||
where
|
||||
M: wiremock::Match + Send + Sync + 'static,
|
||||
{
|
||||
let (mock, response_mock) = compact_mock();
|
||||
mock.and(matcher)
|
||||
.respond_with(
|
||||
ResponseTemplate::new(200)
|
||||
.insert_header("content-type", "application/json")
|
||||
.set_body_json(body.clone()),
|
||||
)
|
||||
.up_to_n_times(1)
|
||||
.mount(server)
|
||||
.await;
|
||||
response_mock
|
||||
}
|
||||
|
||||
pub async fn mount_compact_json_once(server: &MockServer, body: serde_json::Value) -> ResponseMock {
|
||||
mount_compact_response_once(
|
||||
server,
|
||||
|
||||
@@ -279,13 +279,6 @@ pub enum ApplyPatchModelOutput {
|
||||
ShellCommandViaHeredoc,
|
||||
}
|
||||
|
||||
/// A collection of different ways the model can output an apply_patch call
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum ShellModelOutput {
|
||||
ShellCommand,
|
||||
// UnifiedExec has its own set of tests
|
||||
}
|
||||
|
||||
/// Returns the permission fields required by test thread-settings overrides.
|
||||
pub fn turn_permission_fields(
|
||||
permission_profile: PermissionProfile,
|
||||
@@ -1023,14 +1016,6 @@ pub struct TestCodexHarness {
|
||||
}
|
||||
|
||||
impl TestCodexHarness {
|
||||
pub async fn new() -> Result<Self> {
|
||||
Self::with_builder(test_codex()).await
|
||||
}
|
||||
|
||||
pub async fn with_config(mutator: impl FnOnce(&mut Config) + Send + 'static) -> Result<Self> {
|
||||
Self::with_builder(test_codex().with_config(mutator)).await
|
||||
}
|
||||
|
||||
pub async fn with_builder(mut builder: TestCodexBuilder) -> Result<Self> {
|
||||
let server = start_mock_server().await;
|
||||
let test = builder.build(&server).await?;
|
||||
@@ -1055,10 +1040,6 @@ impl TestCodexHarness {
|
||||
self.test.config.cwd.as_path()
|
||||
}
|
||||
|
||||
pub fn cwd_abs(&self) -> AbsolutePathBuf {
|
||||
self.test.config.cwd.clone()
|
||||
}
|
||||
|
||||
pub fn path(&self, rel: impl AsRef<Path>) -> PathBuf {
|
||||
self.path_abs(rel).into_path_buf()
|
||||
}
|
||||
@@ -1160,16 +1141,6 @@ impl TestCodexHarness {
|
||||
Box::pin(self.test.submit_turn(prompt)).await
|
||||
}
|
||||
|
||||
pub async fn submit_with_policy(
|
||||
&self,
|
||||
prompt: &str,
|
||||
sandbox_policy: SandboxPolicy,
|
||||
) -> Result<()> {
|
||||
self.test
|
||||
.submit_turn_with_policy(prompt, sandbox_policy)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn submit_with_permission_profile(
|
||||
&self,
|
||||
prompt: &str,
|
||||
|
||||
@@ -625,14 +625,6 @@ impl ExecServerClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn initialize(
|
||||
&self,
|
||||
options: ExecServerClientConnectOptions,
|
||||
) -> Result<InitializeResponse, ExecServerError> {
|
||||
let rpc_client = self.rpc_client().await?;
|
||||
self.initialize_rpc(&rpc_client, options).await
|
||||
}
|
||||
|
||||
async fn initialize_rpc(
|
||||
&self,
|
||||
rpc_client: &RpcClient,
|
||||
|
||||
@@ -332,12 +332,6 @@ impl EnvironmentManager {
|
||||
self.local_environment.as_ref().map(Arc::clone)
|
||||
}
|
||||
|
||||
/// Returns the default environment or local environment when either exists.
|
||||
pub fn default_or_local_environment(&self) -> Option<Arc<Environment>> {
|
||||
self.default_environment()
|
||||
.or_else(|| self.try_local_environment())
|
||||
}
|
||||
|
||||
/// Returns a named environment instance.
|
||||
pub fn get_environment(&self, environment_id: &str) -> Option<Arc<Environment>> {
|
||||
self.environments
|
||||
|
||||
@@ -7,7 +7,6 @@ use codex_protocol::capabilities::SelectedCapabilityRoot;
|
||||
|
||||
use crate::Environment;
|
||||
use crate::EnvironmentManager;
|
||||
use crate::ExecutorFileSystem;
|
||||
|
||||
/// A selected capability root paired with its currently ready environment handle.
|
||||
///
|
||||
@@ -37,10 +36,6 @@ impl ResolvedSelectedCapabilityRoot {
|
||||
pub fn environment(&self) -> &Arc<Environment> {
|
||||
&self.environment
|
||||
}
|
||||
|
||||
pub fn file_system(&self) -> Arc<dyn ExecutorFileSystem> {
|
||||
self.environment.get_filesystem()
|
||||
}
|
||||
}
|
||||
|
||||
impl EnvironmentManager {
|
||||
|
||||
@@ -11,7 +11,6 @@ use std::process::ExitStatus;
|
||||
use tokio::fs::create_dir_all;
|
||||
use tokio::process::Child;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
async fn spawn_command_under_sandbox(
|
||||
command: Vec<String>,
|
||||
command_cwd: AbsolutePathBuf,
|
||||
@@ -27,6 +26,12 @@ async fn spawn_command_under_sandbox(
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use std::process::Stdio;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
let codex_linux_sandbox_exe = Some(
|
||||
core_test_support::find_codex_linux_sandbox_exe()
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::NotFound, err))?,
|
||||
);
|
||||
#[cfg(target_os = "macos")]
|
||||
let codex_linux_sandbox_exe = None;
|
||||
let exec_request = build_exec_request(
|
||||
ExecParams {
|
||||
@@ -86,33 +91,6 @@ async fn spawn_command_under_sandbox(
|
||||
child.kill_on_drop(true).spawn()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn spawn_command_under_sandbox(
|
||||
command: Vec<String>,
|
||||
command_cwd: AbsolutePathBuf,
|
||||
permission_profile: &PermissionProfile,
|
||||
sandbox_cwd: &AbsolutePathBuf,
|
||||
stdio_policy: StdioPolicy,
|
||||
env: HashMap<String, String>,
|
||||
) -> std::io::Result<Child> {
|
||||
use codex_core::spawn_command_under_linux_sandbox;
|
||||
|
||||
let codex_linux_sandbox_exe = core_test_support::find_codex_linux_sandbox_exe()
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::NotFound, err))?;
|
||||
spawn_command_under_linux_sandbox(
|
||||
codex_linux_sandbox_exe,
|
||||
command,
|
||||
command_cwd,
|
||||
permission_profile,
|
||||
sandbox_cwd,
|
||||
/*use_legacy_landlock*/ false,
|
||||
stdio_policy,
|
||||
/*network*/ None,
|
||||
env,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
/// Determines whether Linux sandbox tests can run on this host.
|
||||
///
|
||||
|
||||
@@ -395,10 +395,6 @@ pub struct FeedbackUploadOptions<'a> {
|
||||
}
|
||||
|
||||
impl FeedbackSnapshot {
|
||||
pub(crate) fn as_bytes(&self) -> &[u8] {
|
||||
&self.bytes
|
||||
}
|
||||
|
||||
pub fn feedback_diagnostics(&self) -> &FeedbackDiagnostics {
|
||||
&self.feedback_diagnostics
|
||||
}
|
||||
@@ -416,14 +412,6 @@ impl FeedbackSnapshot {
|
||||
self.feedback_diagnostics.attachment_text()
|
||||
}
|
||||
|
||||
pub fn save_to_temp_file(&self) -> io::Result<PathBuf> {
|
||||
let dir = std::env::temp_dir();
|
||||
let filename = format!("codex-feedback-{}.log", self.thread_id);
|
||||
let path = dir.join(filename);
|
||||
fs::write(&path, self.as_bytes())?;
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
/// Upload feedback to Sentry with optional attachments.
|
||||
pub fn upload_feedback(&self, options: FeedbackUploadOptions<'_>) -> Result<()> {
|
||||
use std::str::FromStr;
|
||||
@@ -728,7 +716,7 @@ mod tests {
|
||||
}
|
||||
let snap = fb.snapshot(/*session_id*/ None);
|
||||
// Capacity 8: after writing 10 bytes, we should keep the last 8.
|
||||
pretty_assertions::assert_eq!(std::str::from_utf8(snap.as_bytes()).unwrap(), "cdefghij");
|
||||
pretty_assertions::assert_eq!(std::str::from_utf8(&snap.bytes).unwrap(), "cdefghij");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -21,7 +21,6 @@ codex-utils-cargo-bin = { workspace = true }
|
||||
rmcp = { workspace = true }
|
||||
os_info = { workspace = true }
|
||||
pretty_assertions = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tokio = { workspace = true, features = [
|
||||
"io-std",
|
||||
|
||||
@@ -12,13 +12,3 @@ pub use mock_model_server::create_mock_responses_server;
|
||||
pub use responses::create_apply_patch_sse_response;
|
||||
pub use responses::create_final_assistant_message_sse_response;
|
||||
pub use responses::create_shell_command_sse_response;
|
||||
use rmcp::model::JsonRpcResponse;
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
pub fn to_response<T: DeserializeOwned>(
|
||||
response: JsonRpcResponse<serde_json::Value>,
|
||||
) -> anyhow::Result<T> {
|
||||
let value = serde_json::to_value(response.result)?;
|
||||
let codex_response = serde_json::from_value(value)?;
|
||||
Ok(codex_response)
|
||||
}
|
||||
|
||||
@@ -361,16 +361,6 @@ pub enum ElicitationRequest {
|
||||
},
|
||||
}
|
||||
|
||||
impl ElicitationRequest {
|
||||
pub fn message(&self) -> &str {
|
||||
match self {
|
||||
Self::Form { message, .. }
|
||||
| Self::OpenAiForm { message, .. }
|
||||
| Self::Url { message, .. } => message,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, TS)]
|
||||
pub struct ElicitationRequestEvent {
|
||||
/// Turn ID that this elicitation belongs to, when known.
|
||||
|
||||
@@ -630,17 +630,6 @@ fn serialize_hook_prompt_fragment(text: &str, hook_run_id: &str) -> Option<Strin
|
||||
.ok()
|
||||
}
|
||||
|
||||
impl AgentMessageItem {
|
||||
pub fn new(content: &[AgentMessageContent]) -> Self {
|
||||
Self {
|
||||
id: new_item_id(),
|
||||
content: content.to_vec(),
|
||||
phase: None,
|
||||
memory_citation: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TurnItem {
|
||||
pub fn id(&self) -> String {
|
||||
match self {
|
||||
|
||||
@@ -106,15 +106,6 @@ impl FileSystemPermissions {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn explicit_path_entries(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (&AbsolutePathBuf, FileSystemAccessMode)> {
|
||||
self.entries.iter().filter_map(|entry| match &entry.path {
|
||||
FileSystemPath::Path { path } => Some((path, entry.access)),
|
||||
FileSystemPath::GlobPattern { .. } | FileSystemPath::Special { .. } => None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn legacy_read_write_roots(&self) -> Option<LegacyReadWriteRoots> {
|
||||
self.as_legacy_permissions()
|
||||
}
|
||||
@@ -1966,13 +1957,6 @@ impl FunctionCallOutputPayload {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn text_content_mut(&mut self) -> Option<&mut String> {
|
||||
match &mut self.body {
|
||||
FunctionCallOutputBody::Text(content) => Some(content),
|
||||
FunctionCallOutputBody::ContentItems(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn content_items(&self) -> Option<&[FunctionCallOutputContentItem]> {
|
||||
match &self.body {
|
||||
FunctionCallOutputBody::Text(_) => None,
|
||||
|
||||
@@ -27,77 +27,3 @@ fn formatter() -> &'static DecimalFormatter {
|
||||
pub fn format_with_separators(n: i64) -> String {
|
||||
formatter().format(&Decimal::from(n)).to_string()
|
||||
}
|
||||
|
||||
fn format_with_separators_with_formatter(n: i64, formatter: &DecimalFormatter) -> String {
|
||||
formatter.format(&Decimal::from(n)).to_string()
|
||||
}
|
||||
|
||||
fn format_si_suffix_with_formatter(n: i64, formatter: &DecimalFormatter) -> String {
|
||||
let n = n.max(0);
|
||||
if n < 1000 {
|
||||
return formatter.format(&Decimal::from(n)).to_string();
|
||||
}
|
||||
|
||||
// Format `n / scale` with the requested number of fractional digits.
|
||||
let format_scaled = |n: i64, scale: i64, frac_digits: u32| -> String {
|
||||
let value = n as f64 / scale as f64;
|
||||
let scaled: i64 = (value * 10f64.powi(frac_digits as i32)).round() as i64;
|
||||
let mut dec = Decimal::from(scaled);
|
||||
dec.multiply_pow10(-(frac_digits as i16));
|
||||
formatter.format(&dec).to_string()
|
||||
};
|
||||
|
||||
const UNITS: [(i64, &str); 3] = [(1_000, "K"), (1_000_000, "M"), (1_000_000_000, "G")];
|
||||
let f = n as f64;
|
||||
for &(scale, suffix) in &UNITS {
|
||||
if (100.0 * f / scale as f64).round() < 1000.0 {
|
||||
return format!("{}{}", format_scaled(n, scale, 2), suffix);
|
||||
} else if (10.0 * f / scale as f64).round() < 1000.0 {
|
||||
return format!("{}{}", format_scaled(n, scale, 1), suffix);
|
||||
} else if (f / scale as f64).round() < 1000.0 {
|
||||
return format!("{}{}", format_scaled(n, scale, 0), suffix);
|
||||
}
|
||||
}
|
||||
|
||||
// Above 1000G, keep whole‑G precision.
|
||||
format!(
|
||||
"{}G",
|
||||
format_with_separators_with_formatter(((n as f64) / 1e9).round() as i64, formatter)
|
||||
)
|
||||
}
|
||||
|
||||
/// Format token counts to 3 significant figures, using base-10 SI suffixes.
|
||||
///
|
||||
/// Examples (en-US):
|
||||
/// - 999 -> "999"
|
||||
/// - 1200 -> "1.20K"
|
||||
/// - 123456789 -> "123M"
|
||||
pub fn format_si_suffix(n: i64) -> String {
|
||||
format_si_suffix_with_formatter(n, formatter())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn kmg() {
|
||||
let formatter = make_en_us_formatter();
|
||||
let fmt = |n: i64| format_si_suffix_with_formatter(n, &formatter);
|
||||
assert_eq!(fmt(0), "0");
|
||||
assert_eq!(fmt(999), "999");
|
||||
assert_eq!(fmt(1_000), "1.00K");
|
||||
assert_eq!(fmt(1_200), "1.20K");
|
||||
assert_eq!(fmt(10_000), "10.0K");
|
||||
assert_eq!(fmt(100_000), "100K");
|
||||
assert_eq!(fmt(999_500), "1.00M");
|
||||
assert_eq!(fmt(1_000_000), "1.00M");
|
||||
assert_eq!(fmt(1_234_000), "1.23M");
|
||||
assert_eq!(fmt(12_345_678), "12.3M");
|
||||
assert_eq!(fmt(999_950_000), "1.00G");
|
||||
assert_eq!(fmt(1_000_000_000), "1.00G");
|
||||
assert_eq!(fmt(1_234_000_000), "1.23G");
|
||||
// Above 1000G we keep whole‑G precision (no higher unit supported here).
|
||||
assert_eq!(fmt(1_234_000_000_000), "1,234G");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,11 +37,6 @@ pub fn is_protected_metadata_name(name: &OsStr) -> bool {
|
||||
.any(|metadata_name| name == OsStr::new(metadata_name))
|
||||
}
|
||||
|
||||
pub fn is_protected_metadata_directory_name(name: &OsStr) -> bool {
|
||||
name == OsStr::new(PROTECTED_METADATA_AGENTS_PATH_NAME)
|
||||
|| name == OsStr::new(PROTECTED_METADATA_CODEX_PATH_NAME)
|
||||
}
|
||||
|
||||
/// Returns the protected workspace metadata name when an agent write to `path`
|
||||
/// should be blocked before execution.
|
||||
pub fn forbidden_agent_metadata_write(
|
||||
|
||||
@@ -501,22 +501,6 @@ where
|
||||
self.previous_buffer_mut().reset();
|
||||
}
|
||||
|
||||
/// Clear terminal scrollback (if supported) and force a full redraw.
|
||||
pub fn clear_scrollback(&mut self) -> io::Result<()> {
|
||||
if self.viewport_area.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let home = Position { x: 0, y: 0 };
|
||||
// Use an explicit cursor-home around scrollback purge for terminals that
|
||||
// are sensitive to inline viewport cursor placement (e.g. Terminal.app).
|
||||
self.set_cursor_position(home)?;
|
||||
queue!(self.backend, Clear(crossterm::terminal::ClearType::Purge))?;
|
||||
self.set_cursor_position(home)?;
|
||||
std::io::Write::flush(&mut self.backend)?;
|
||||
self.previous_buffer_mut().reset();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Clear the entire visible screen (not just the viewport) and force a full redraw.
|
||||
pub fn clear_visible_screen(&mut self) -> io::Result<()> {
|
||||
let home = Position { x: 0, y: 0 };
|
||||
@@ -551,10 +535,6 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn visible_history_rows(&self) -> u16 {
|
||||
self.visible_history_rows
|
||||
}
|
||||
|
||||
pub(crate) fn note_history_rows_inserted(&mut self, inserted_rows: u16) {
|
||||
self.visible_history_rows = self
|
||||
.visible_history_rows
|
||||
|
||||
@@ -35,7 +35,7 @@ impl HistoryCell for UpdateAvailableHistoryCell {
|
||||
|
||||
let content = text![
|
||||
line![
|
||||
padded_emoji("✨").bold().cyan(),
|
||||
"✨\u{200A}".bold().cyan(),
|
||||
"Update available!".bold().cyan(),
|
||||
" ",
|
||||
format!("{CODEX_CLI_VERSION} -> {}", self.latest_version).bold(),
|
||||
|
||||
@@ -71,13 +71,6 @@ fn with_border_internal(
|
||||
out
|
||||
}
|
||||
|
||||
/// Return the emoji followed by a hair space (U+200A).
|
||||
/// Using only the hair space avoids excessive padding after the emoji while
|
||||
/// still providing a small visual gap across terminals.
|
||||
pub(crate) fn padded_emoji(emoji: &str) -> String {
|
||||
format!("{emoji}\u{200A}")
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TooltipHistoryCell {
|
||||
tip: String,
|
||||
|
||||
@@ -35,10 +35,6 @@ impl RowBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn width(&self) -> usize {
|
||||
self.target_width
|
||||
}
|
||||
|
||||
pub fn set_width(&mut self, width: usize) {
|
||||
self.target_width = width.max(1);
|
||||
// Rewrap everything we have (simple approach for Step 1).
|
||||
@@ -76,11 +72,6 @@ impl RowBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark the end of the current logical line (equivalent to pushing a '\n').
|
||||
pub fn end_line(&mut self) {
|
||||
self.flush_current_line(/*explicit_break*/ true);
|
||||
}
|
||||
|
||||
/// Return a snapshot of produced rows (non-draining).
|
||||
pub fn rows(&self) -> &[Row] {
|
||||
&self.rows
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#![cfg(not(debug_assertions))]
|
||||
|
||||
use crate::history_cell::padded_emoji;
|
||||
use crate::key_hint;
|
||||
use crate::legacy_core::config::Config;
|
||||
use crate::render::Insets;
|
||||
@@ -192,7 +191,7 @@ impl WidgetRef for &UpdatePromptScreen {
|
||||
|
||||
column.push("");
|
||||
column.push(Line::from(vec![
|
||||
padded_emoji(" ✨").bold().cyan(),
|
||||
" ✨\u{200A}".bold().cyan(),
|
||||
"Update available!".bold(),
|
||||
" ".into(),
|
||||
format!(
|
||||
|
||||
@@ -82,17 +82,6 @@ impl CliConfigOverrides {
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Apply all parsed overrides onto `target`. Intermediate objects will be
|
||||
/// created as necessary. Values located at the destination path will be
|
||||
/// replaced.
|
||||
pub fn apply_on_value(&self, target: &mut Value) -> Result<(), String> {
|
||||
let overrides = self.parse_overrides()?;
|
||||
for (path, value) in overrides {
|
||||
apply_single_override(target, &path, value);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn canonicalize_override_key(key: &str) -> String {
|
||||
@@ -103,50 +92,6 @@ fn canonicalize_override_key(key: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply a single override onto `root`, creating intermediate objects as
|
||||
/// necessary.
|
||||
fn apply_single_override(root: &mut Value, path: &str, value: Value) {
|
||||
use toml::value::Table;
|
||||
|
||||
let parts: Vec<&str> = path.split('.').collect();
|
||||
let mut current = root;
|
||||
|
||||
for (i, part) in parts.iter().enumerate() {
|
||||
let is_last = i == parts.len() - 1;
|
||||
|
||||
if is_last {
|
||||
match current {
|
||||
Value::Table(tbl) => {
|
||||
tbl.insert((*part).to_string(), value);
|
||||
}
|
||||
_ => {
|
||||
let mut tbl = Table::new();
|
||||
tbl.insert((*part).to_string(), value);
|
||||
*current = Value::Table(tbl);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Traverse or create intermediate table.
|
||||
match current {
|
||||
Value::Table(tbl) => {
|
||||
current = tbl
|
||||
.entry((*part).to_string())
|
||||
.or_insert_with(|| Value::Table(Table::new()));
|
||||
}
|
||||
_ => {
|
||||
*current = Value::Table(Table::new());
|
||||
if let Value::Table(tbl) = current {
|
||||
current = tbl
|
||||
.entry((*part).to_string())
|
||||
.or_insert_with(|| Value::Table(Table::new()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_toml_value(raw: &str) -> Result<Value, toml::de::Error> {
|
||||
let wrapped = format!("_x_ = {raw}");
|
||||
let table: toml::Table = toml::from_str(&wrapped)?;
|
||||
|
||||
@@ -8,8 +8,6 @@ license.workspace = true
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
codex-core = { workspace = true }
|
||||
codex-model-provider-info = { workspace = true }
|
||||
codex-protocol = { workspace = true }
|
||||
codex-utils-absolute-path = { workspace = true }
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
use codex_core::config::Config;
|
||||
use codex_model_provider_info::WireApi;
|
||||
|
||||
use crate::sandbox_summary::summarize_sandbox_policy;
|
||||
|
||||
/// Build a list of key/value pairs summarizing the effective configuration.
|
||||
pub fn create_config_summary_entries(config: &Config, model: &str) -> Vec<(&'static str, String)> {
|
||||
let mut entries = vec![
|
||||
("workdir", config.cwd.display().to_string()),
|
||||
("model", model.to_string()),
|
||||
("provider", config.model_provider_id.clone()),
|
||||
(
|
||||
"approval",
|
||||
config.permissions.approval_policy.value().to_string(),
|
||||
),
|
||||
(
|
||||
"sandbox",
|
||||
summarize_sandbox_policy(
|
||||
&config
|
||||
.permissions
|
||||
.legacy_sandbox_policy(config.cwd.as_path()),
|
||||
),
|
||||
),
|
||||
];
|
||||
if config.model_provider.wire_api == WireApi::Responses {
|
||||
let reasoning_effort = config
|
||||
.model_reasoning_effort
|
||||
.as_ref()
|
||||
.map(std::string::ToString::to_string);
|
||||
entries.push((
|
||||
"reasoning effort",
|
||||
reasoning_effort.unwrap_or_else(|| "none".to_string()),
|
||||
));
|
||||
entries.push((
|
||||
"reasoning summaries",
|
||||
config
|
||||
.model_reasoning_summary
|
||||
.map(|summary| summary.to_string())
|
||||
.unwrap_or_else(|| "none".to_string()),
|
||||
));
|
||||
}
|
||||
|
||||
entries
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
mod config_summary;
|
||||
mod sandbox_summary;
|
||||
|
||||
pub use config_summary::create_config_summary_entries;
|
||||
pub use sandbox_summary::summarize_permission_profile;
|
||||
pub use sandbox_summary::summarize_sandbox_policy;
|
||||
|
||||
Reference in New Issue
Block a user