Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
804d630
Allow approved filesystem escalation while preserving denied reads (#…
viyatb-oai Sep 29, 2026
1983c48
Continue Markdown blockquotes when pasting multiline text (#49357)
bc-openai Sep 29, 2026
995138d
Carry shell invocation metadata and report executor PATH directories …
anp-oai Sep 29, 2026
94d642d
Clarify credential storage wording across authentication UI and docs …
celia-oai Sep 29, 2026
2a34aef
Update Bedrock GPT-6 Sol catalog tests to expect multi-agent V2 (#49369)
celia-oai Sep 29, 2026
bd4204e
Compile hook matchers during discovery (#49379)
jif-oai Sep 29, 2026
a44afa5
Track credential storage outcomes and redact sensitive errors (#49384)
celia-oai Sep 29, 2026
d657132
Fix Windows path inference for opaque URIs with slash prefixes (#49388)
dkovalenko-oai Sep 29, 2026
9212b3e
Serialize tests that share Windows sandbox accounts (#49389)
jgershen-oai Sep 29, 2026
05ea5f7
Add attributed MCP OAuth credential storage telemetry (#49392)
celia-oai Sep 29, 2026
ceea671
Remove randomized greetings from TUI session headers (#49395)
etraut-openai Sep 29, 2026
87d3e06
Preserve live tool-call metadata across request windows (#49401)
ningyi-oai Sep 29, 2026
17a9df6
Add an experimental flag for bundled tools in login shells (#49403)
anp-oai Sep 29, 2026
7c35e15
Support explicit cyber access programs with OpenAI API keys (#49406)
julee-oai Sep 29, 2026
67352b5
Recover exec-server sessions after environment info timeouts (#49407)
vivi Sep 30, 2026
bd51858
Compare tool call metadata in the recorder refresh test (#49408)
euroelessar Sep 30, 2026
eefe0ce
Bind the app-server time provider to a local variable (#49411)
euroelessar Sep 30, 2026
16a7c0f
Filter graceful shutdown guard and trigger traces from SQLite logs (#…
dkovalenko-oai Sep 30, 2026
d940fb2
Truncate input text in protocol debug output (#49415)
dkovalenko-oai Sep 30, 2026
ab84d71
Omit payloads from multiline ANSI warnings (#49416)
dkovalenko-oai Sep 30, 2026
d1d0e89
Infer Windows UNC paths with forward and mixed slashes (#49424)
dkovalenko-oai Sep 30, 2026
8ea2c0e
Prune diagnostic logs periodically by age and database size (#49425)
dkovalenko-oai Sep 30, 2026
2cc65cd
Enable analytics by default for daemon-launched app servers (#49426)
bc-openai Sep 30, 2026
d8f69ea
Preserve bootstrap discovery across authentication changes (#49432)
cooper-oai Sep 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions codex-rs/.config/nextest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ max-threads = 1
[test-groups.windows_sandbox_legacy_sessions]
max-threads = 1

[test-groups.windows_sandbox_accounts]
max-threads = 1

[test-groups.windows_process_heavy]
max-threads = 2

Expand Down Expand Up @@ -82,6 +85,23 @@ test-group = 'app_server_integration_local'
filter = 'package(codex-core) & kind(test) & test(apply_patch_cli)'
test-group = 'core_apply_patch_cli_integration'

[[profile.default.overrides]]
# These cases share the runner's elevated sandbox accounts. Queue them before
# starting their timeout; their file lock still coordinates other test processes.
platform = 'cfg(windows)'
filter = '''
(package(codex-core) & (
test(windows_sandbox_cli_preserves_managed_deny_reads_across_launches) |
test(windows_elevated_does_not_create_missing_workspace_metadata) |
test(windows_elevated_enforces_deny_read_and_protects_setup_marker) |
test(windows_elevated_unified_exec_enforces_large_recursive_deny_reads) |
test(windows_elevated_approved_git_pull_preserves_deny_read)
)) |
(package(codex-exec-server) & test(file_system_elevated_relative_read_denial_uses_policy_cwd)) |
(package(codex-windows-sandbox) & test(elevated_non_tty_cmd_forwards_env_output_and_exit))
'''
test-group = 'windows_sandbox_accounts'

[[profile.default.overrides]]
# These tests create restricted-token Windows child processes and private desktops.
# Serialize them to avoid exhausting Windows session/global desktop resources in CI.
Expand Down
16 changes: 16 additions & 0 deletions codex-rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions codex-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ members = [
"v8-poc",
"websocket-auth",
"websocket-client",
"windows-sandbox-rs/tests/support",
"windows-sandbox-service",
"worktree",
"workload-identity",
Expand Down Expand Up @@ -316,6 +317,7 @@ codex-user-verification = { path = "user-verification" }
codex-v8-poc = { path = "v8-poc" }
codex-workload-identity = { path = "workload-identity" }
codex-windows-sandbox = { path = "windows-sandbox-rs" }
codex-windows-sandbox-test-support = { path = "windows-sandbox-rs/tests/support" }
core_test_support = { path = "core/tests/common" }

# External
Expand Down
5 changes: 4 additions & 1 deletion codex-rs/ansi-escape/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ license.workspace = true
[lib]
name = "codex_ansi_escape"
path = "src/lib.rs"
test = false
doctest = false

[lints]
Expand All @@ -17,3 +16,7 @@ workspace = true
ansi-to-tui = { workspace = true }
ratatui = { workspace = true }
tracing = { workspace = true, features = ["log"] }

[dev-dependencies]
pretty_assertions = { workspace = true }
tracing-subscriber = { workspace = true }
76 changes: 76 additions & 0 deletions codex-rs/ansi-escape/src/ansi_escape_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//! Check that multiline warnings omit payloads and preserve first-line rendering.
use std::collections::BTreeMap;
use std::sync::Arc;
use std::sync::Mutex;

use pretty_assertions::assert_eq;
use ratatui::style::Stylize;
use ratatui::text::Line;
use tracing::Event;
use tracing::Level;
use tracing::Subscriber;
use tracing::field::Field;
use tracing::field::Visit;
use tracing_subscriber::Layer;
use tracing_subscriber::layer::Context;
use tracing_subscriber::layer::SubscriberExt;

use super::ansi_escape_line;

#[derive(Debug, PartialEq, Eq)]
struct CapturedEvent {
level: Level,
fields: BTreeMap<String, String>,
}

impl Visit for CapturedEvent {
fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) {
self.fields
.insert(field.name().to_string(), format!("{value:?}"));
}
}

struct CaptureLayer(Arc<Mutex<Vec<CapturedEvent>>>);

impl<S: Subscriber> Layer<S> for CaptureLayer {
fn on_event(&self, event: &Event<'_>, _ctx: Context<'_, S>) {
let mut captured = CapturedEvent {
level: *event.metadata().level(),
fields: BTreeMap::new(),
};
event.record(&mut captured);
self.0.lock().expect("capture events").push(captured);
}
}

#[test]
fn multiline_warning_contains_counts_and_preserves_the_styled_first_line() {
let events = Arc::new(Mutex::new(Vec::new()));
let subscriber = tracing_subscriber::registry().with(CaptureLayer(Arc::clone(&events)));
let mut expected_events = Vec::new();

tracing::subscriber::with_default(subscriber, || {
for tail_bytes in [8, 128 * 1024] {
let tail = "x".repeat(tail_bytes);
let input = format!("\x1b[31mfirst\x1b[0m\n{tail}\nlast");
assert_eq!(ansi_escape_line(&input), Line::from("first".red()));
expected_events.push(CapturedEvent {
level: Level::WARN,
fields: BTreeMap::from([
("input_bytes".to_string(), input.len().to_string()),
("line_count".to_string(), "3".to_string()),
(
"message".to_string(),
"ansi_escape_line: expected a single line".to_string(),
),
]),
});
}
});

assert_eq!(
*events.lock().expect("read captured events"),
expected_events
);
}
10 changes: 9 additions & 1 deletion codex-rs/ansi-escape/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ pub fn ansi_escape_line(s: &str) -> Line<'static> {
[] => "".into(),
[only] => only.clone(),
[first, rest @ ..] => {
tracing::warn!("ansi_escape_line: expected a single line, got {first:?} and {rest:?}");
tracing::warn!(
input_bytes = s.len(),
line_count = rest.len() + 1,
"ansi_escape_line: expected a single line"
);
first.clone()
}
}
Expand All @@ -56,3 +60,7 @@ pub fn ansi_escape(s: &str) -> Text<'static> {
},
}
}

#[cfg(test)]
#[path = "ansi_escape_tests.rs"]
mod tests;
2 changes: 2 additions & 0 deletions codex-rs/app-server-daemon/src/backend/pid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,8 @@ impl PidBackend {
}
};
if matches!(self.command_kind, PidCommandKind::AppServer { .. }) {
// Match first-party clients' default while preserving explicit analytics opt-outs.
args.push("--analytics-default-enabled".into());
for (name, enabled) in &self.feature_overrides {
args.extend(["-c".into(), format!("features.{name}={enabled}").into()]);
}
Expand Down
15 changes: 13 additions & 2 deletions codex-rs/app-server-daemon/src/backend/pid_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,13 @@ fn app_server_remote_control_uses_runtime_flag() {

assert_eq!(
backend.command_args(),
vec!["app-server", "--remote-control", "--listen", "unix://"]
vec![
"app-server",
"--remote-control",
"--listen",
"unix://",
"--analytics-default-enabled"
]
);
}

Expand All @@ -616,7 +622,12 @@ fn app_server_disabled_remote_control_uses_compatible_args_and_runtime_env() {

assert_eq!(
backend.command_args(),
vec!["app-server", "--listen", "unix://"]
vec![
"app-server",
"--listen",
"unix://",
"--analytics-default-enabled"
]
);
assert_eq!(
backend.command_env(),
Expand Down
4 changes: 2 additions & 2 deletions codex-rs/app-server-daemon/src/update_loop_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,9 +584,9 @@ async fn daemon_start_and_restart_preserve_launch_features() {
features
);
let expected = if features.is_empty() {
"app-server\n--listen\nunix://\n--managed-daemon\n"
"app-server\n--listen\nunix://\n--analytics-default-enabled\n--managed-daemon\n"
} else {
"app-server\n--listen\nunix://\n-c\nfeatures.api_key_model_discovery=true\n-c\nfeatures.code_mode_host=false\n--managed-daemon\n"
"app-server\n--listen\nunix://\n--analytics-default-enabled\n-c\nfeatures.api_key_model_discovery=true\n-c\nfeatures.code_mode_host=false\n--managed-daemon\n"
};
assert_eq!(std::fs::read_to_string(&args_path).unwrap(), expected);
let reused = daemon
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions codex-rs/app-server-protocol/src/protocol/v2/turn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ pub struct AdditionalContextEntry {
pub kind: AdditionalContextKind,
}

/// Requested cyber treatment for a ChatGPT-authenticated Codex turn.
/// Requested cyber treatment for an OpenAI model turn.
/// Authorization and model-tier restrictions remain server-owned.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -271,7 +271,7 @@ pub struct TurnStartParams {
#[ts(optional = nullable)]
pub multi_agent_mode: Option<MultiAgentMode>,

/// EXPERIMENTAL - Request a workspace-authorized cyber program for this
/// EXPERIMENTAL - Request an authorized cyber program for this
/// turn. Omission preserves automatic behavior. This does not grant access.
#[experimental("turn/start.cyberAccessProgram")]
#[ts(optional = nullable)]
Expand Down
9 changes: 9 additions & 0 deletions codex-rs/app-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ after a client tries to archive or delete it.
After the owner releases the worker, its saved conversation can be archived or
deleted normally. Ordinary client-controlled threads keep their existing behavior.

## Environment information (experimental)

`environment/info` connects to a configured environment by `environmentId` and
returns its detected `shell` plus its default `cwd` as a canonical
environment-native `file:` URI. Connection failures are returned as request
errors. After connecting, the live metadata request has a 30-second timeout. A
timeout closes the probed connection and starts normal session recovery without
retrying the failed request.

## User verification (experimental)

Codex app-server advertises `openai/elicitation.userVerification` to the
Expand Down
3 changes: 2 additions & 1 deletion codex-rs/app-server/src/in_process_bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ impl EmbeddedNetworkPolicy {
.restrict_to_endpoints(endpoint.parse().into_iter().collect()),
),
)
.with_local_bootstrap_factory(factory);
.with_local_bootstrap_factory(factory)
.with_application_network_policy(self.effective.policy());
auth
}
}
Expand Down
Loading
Loading