Commit Graph

8472 Commits

Author SHA1 Message Date
Michael Bolin
a8ae76a5ae merge commit for archive created by Sapling 2026-02-25 13:33:25 -08:00
Michael Bolin
43daba8cb6 feat: scope execve session approvals by approved skill metadata 2026-02-25 13:33:16 -08:00
Michael Bolin
1acbef8d92 merge commit for archive created by Sapling 2026-02-25 13:11:49 -08:00
Michael Bolin
ddf331f618 feat: scope execve session approvals by approved skill metadata 2026-02-25 13:11:38 -08:00
Michael Bolin
e87fabb967 Merge 4eaec7be7d into sapling-pr-archive-bolinfest 2026-02-25 13:02:32 -08:00
Michael Bolin
2383104d3f feat: include available decisions in command approval requests 2026-02-25 13:02:23 -08:00
Michael Bolin
4eaec7be7d feat: scope execve session approvals by approved skill metadata 2026-02-25 13:02:23 -08:00
Michael Bolin
4cae7ce19c Merge a8d528affb into sapling-pr-archive-bolinfest 2026-02-25 12:37:47 -08:00
Michael Bolin
a8d528affb feat: scope execve session approvals by approved skill metadata 2026-02-25 12:37:28 -08:00
Michael Bolin
86b4ebc19e Merge 7d9c3547fe into sapling-pr-archive-bolinfest 2026-02-25 12:30:11 -08:00
Michael Bolin
f523c45e65 feat: include available decisions in command approval requests 2026-02-25 12:29:40 -08:00
Michael Bolin
7d9c3547fe feat: scope execve session approvals by approved skill metadata 2026-02-25 12:29:40 -08:00
Michael Bolin
be5bca6f8d fix: harden zsh fork tests and keep subcommand approvals deterministic (#12809)
## Why
The prior
`turn_start_shell_zsh_fork_subcommand_decline_marks_parent_declined_v2`
assertion was brittle under Bazel: command approval payloads in the test
could include environment-dependent wrapper/command formatting
differences, which makes exact command-string matching flaky even when
behavior is correct.

(This regression was knowingly introduced in
https://github.com/openai/codex/pull/12800, but it was urgent to land
that PR.)

## What changed
- Hardened
`turn_start_shell_zsh_fork_subcommand_decline_marks_parent_declined_v2`
in
[`turn_start_zsh_fork.rs`](https://github.com/openai/codex/blob/main/codex-rs/app-server/tests/suite/v2/turn_start_zsh_fork.rs):
- Replaced strict `approval_command.starts_with("/bin/rm")` checks with
intent-based subcommand matching.
- Subcommand approvals are now recognized by file-target semantics
(`first.txt` or `second.txt`) plus `rm` intent.
- Parent approval recognition is now more tolerant of command-format
differences while still requiring a definitive parent command context.
- Uses a defensive loop that waits for all target subcommand decisions
and the parent approval request.
- Preserved the existing regression and unit test fixes from earlier
commits in `unix_escalation.rs` and `skill_approval.rs`.

## Verification
- Ran the zsh fork subcommand decline regression under this change:
-
`turn_start_shell_zsh_fork_subcommand_decline_marks_parent_declined_v2`
- Confirmed the test is now robust against approval-command-string
variation instead of hardcoding one expected command shape.
2026-02-25 12:23:30 -08:00
Eric Traut
f6fdfbeb98 Update Codex docs success link (#12805)
Fix a stale documentation link in the sign-in flow
2026-02-25 12:02:41 -08:00
Ahmed Ibrahim
3f30746237 Add simple realtime text logs (#12807)
Update realtime debug logs to include the actual text payloads in both
input and output paths.

- In `core/src/realtime_conversation.rs`:
- `handle_start`: add extracted assistant text output to the
`[realtime-text]` debug log.
- `handle_text`: add incoming text input (`params.text`) to the
`[realtime-text]` debug log.

No tests were run (per request).
2026-02-25 12:01:48 -08:00
Owen Lin
a0fd94bde6 feat(app-server): add ThreadItem::DynamicToolCall (#12732)
Previously, clients would call `thread/start` with dynamic_tools set,
and when a model invokes a dynamic tool, it would just make the
server->client `item/tool/call` request and wait for the client's
response to complete the tool call. This works, but it doesn't have an
`item/started` or `item/completed` event.

Now we are doing this:
- [new] emit `item/started` with `DynamicToolCall` populated with the
call arguments
- send an `item/tool/call` server request
- [new] once the client responds, emit `item/completed` with
`DynamicToolCall` populated with the response.

Also, with `persistExtendedHistory: true`, dynamic tool calls are now
reconstructable in `thread/read` and `thread/resume` as
`ThreadItem::DynamicToolCall`.
2026-02-25 12:00:10 -08:00
Michael Bolin
685b91c326 Merge dd82918404 into sapling-pr-archive-bolinfest 2026-02-25 11:20:26 -08:00
Michael Bolin
dd82918404 fix: make turn_start_shell_zsh_fork_subcommand_decline_marks_parent_declined_v2 succeed on Bazel 2026-02-25 11:20:18 -08:00
Rasmus Rygaard
73eaebbd1c Propagate session ID when compacting (#12802)
We propagate the session ID when sending requests for inference but we
don't do the same for compaction requests. This makes it hard to link
compaction requests to their session for debugging purposes
2026-02-25 19:17:38 +00:00
Michael Bolin
648a420cbf fix: enforce sandbox envelope for zsh fork execution (#12800)
## Why
Zsh fork execution was still able to bypass the `WorkspaceWrite` model
in edge cases because the fork path reconstructed command execution
without preserving sandbox wrappers, and command extraction only
accepted shell invocations in a narrow positional shape. This can allow
commands to run with broader filesystem access than expected, which
breaks the sandbox safety model.

## What changed
- Preserved the sandboxed `ExecRequest` produced by
`attempt.env_for(...)` when entering the zsh fork path in
[`unix_escalation.rs`](https://github.com/openai/codex/blob/main/codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs).
- Updated `CoreShellCommandExecutor` to execute the sandboxed command
and working directory captured from `attempt.env_for(...)`, instead of
re-running a freshly reconstructed shell command.
- Made zsh-fork script extraction robust to wrapped invocations by
scanning command arguments for `-c`/`-lc` rather than only matching the
first positional form.
- Added unit tests in `unix_escalation.rs` to lock in wrapper-tolerant
parsing behavior and keep unsupported shell forms rejected.
- Tightened the regression in
[`skill_approval.rs`](https://github.com/openai/codex/blob/main/codex-rs/core/tests/suite/skill_approval.rs):
- `shell_zsh_fork_still_enforces_workspace_write_sandbox` now uses an
explicit `WorkspaceWrite` policy with `exclude_tmpdir_env_var: true` and
`exclude_slash_tmp: true`.
- The test attempts to write to `/tmp/...`, which is only reliably
outside writable roots with those explicit exclusions set.

## Verification
- Added and passed the new unit tests around `extract_shell_script`
parsing behavior with wrapped command shapes.
  - `extract_shell_script_supports_wrapped_command_prefixes`
  - `extract_shell_script_rejects_unsupported_shell_invocation`
- Verified the regression with the focused integration test:
`shell_zsh_fork_still_enforces_workspace_write_sandbox`.

## Manual Testing

Prior to this change, if I ran Codex via:

```
just codex --config zsh_path=/Users/mbolin/code/codex2/codex-rs/app-server/tests/suite/zsh --enable shell_zsh_fork
```

and asked:

```
what is the output of /bin/ps
```

it would run it, even though the default sandbox should prevent the
agent from running `/bin/ps` because it is setuid on MacOS.

But with this change, I now see the expected failure because it is
blocked by the sandbox:

```
/bin/ps exited with status 1 and produced no output in this environment.
```
2026-02-25 11:05:27 -08:00
Michael Bolin
c79fe45647 merge commit for archive created by Sapling 2026-02-25 10:54:18 -08:00
Michael Bolin
0bef1901f7 fix: zsh-shell-fork was not honoring sandbox 2026-02-25 10:54:10 -08:00
Michael Bolin
1fb2583be8 merge commit for archive created by Sapling 2026-02-25 10:47:40 -08:00
Michael Bolin
e94c837e7c fix: zsh-shell-fork was not honoring sandbox 2026-02-25 10:47:30 -08:00
Michael Bolin
53a0a2457b Merge 520ae99801 into sapling-pr-archive-bolinfest 2026-02-25 10:38:26 -08:00
Michael Bolin
520ae99801 fix: zsh-shell-fork was not honoring sandbox 2026-02-25 10:38:17 -08:00
pakrym-oai
9d7013eab0 Handle websocket timeout (#12791)
Sometimes websockets will timeout with 400 error, ensure we retry it.
2026-02-25 10:31:37 -08:00
jif-oai
7b39e76a66 Revert "fix(bazel): replace askama templates with include_str! in memories" (#12795)
Reverts openai/codex#11778
2026-02-25 18:06:17 +00:00
Ahmed Ibrahim
947092283a Add app-server v2 thread realtime API (#12715)
Add experimental `thread/realtime/*` v2 requests and notifications, then
route app-server realtime events through that thread-scoped surface with
integration coverage.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-02-25 09:59:10 -08:00
Curtis 'Fjord' Hawthorne
0543d0a022 Promote js_repl to experimental with Node requirement (#12712)
## Summary

- Promote `js_repl` to an experimental feature that users can enable
from `/experimental`.
- Add `js_repl` experimental metadata, including the Node prerequisite
and activation guidance.
- Add regression coverage for the feature metadata and the
`/experimental` popup.

## What Changed

- Changed `Feature::JsRepl` from `Stage::UnderDevelopment` to
`Stage::Experimental`.
- Added experimental metadata for `js_repl` in `core/src/features.rs`:
  - name: `JavaScript REPL`
- description: calls out interactive website debugging, inline
JavaScript execution, and the required Node version (`>= v24.13.1`)
- announcement: tells users to enable it, then start a new chat or
restart Codex
- Added a core unit test that verifies:
  - `js_repl` is experimental
  - `js_repl` is disabled by default
- the hardcoded Node version in the description matches
`node-version.txt`
- Added a TUI test that opens the `/experimental` popup and verifies the
rendered `js_repl` entry includes the Node requirement text.

## Testing

- `just fmt`
- `cargo test -p codex-tui`
- `cargo test -p codex-core` (unit-test phase passed; stopped during the
long `tests/all.rs` integration suite)
2026-02-25 09:44:52 -08:00
Michael Bolin
593630a088 merge commit for archive created by Sapling 2026-02-25 09:21:52 -08:00
Michael Bolin
e045e06d6c feat: include availableDecisions with command approvals 2026-02-25 09:19:43 -08:00
Michael Bolin
662dd1a40e Merge 05544a1e27 into sapling-pr-archive-bolinfest 2026-02-25 09:10:42 -08:00
Michael Bolin
05544a1e27 feat: include availableDecisions with command approvals 2026-02-25 09:10:20 -08:00
mcgrew-oai
9a393c9b6f feat(network-proxy): add embedded OTEL policy audit logging (#12046)
**PR Summary**

This PR adds embedded-only OTEL policy audit logging for
`codex-network-proxy` and threads audit metadata from `codex-core` into
managed proxy startup.

### What changed
- Added structured audit event emission in `network_policy.rs` with
target `codex_otel.network_proxy`.
- Emitted:
- `codex.network_proxy.domain_policy_decision` once per domain-policy
evaluation.
  - `codex.network_proxy.block_decision` for non-domain denies.
- Added required policy/network fields, RFC3339 UTC millisecond
`event.timestamp`, and fallback defaults (`http.request.method="none"`,
`client.address="unknown"`).
- Added non-domain deny audit emission in HTTP/SOCKS handlers for
mode-guard and proxy-state denies, including unix-socket deny paths.
- Added `REASON_UNIX_SOCKET_UNSUPPORTED` and used it for unsupported
unix-socket auditing.
- Added `NetworkProxyAuditMetadata` to runtime/state, re-exported from
`lib.rs` and `state.rs`.
- Added `start_proxy_with_audit_metadata(...)` in core config, with
`start_proxy()` delegating to default metadata.
- Wired metadata construction in `codex.rs` from session/auth context,
including originator sanitization for OTEL-safe tagging.
- Updated `network-proxy/README.md` with embedded-mode audit schema and
behavior notes.
- Refactored HTTP block-audit emission to a small local helper to reduce
duplication.
- Preserved existing unix-socket proxy-disabled host/path behavior for
responses and blocked history while using an audit-only endpoint
override (`server.address="unix-socket"`, `server.port=0`).

### Explicit exclusions
- No standalone proxy OTEL startup work.
- No `main.rs` binary wiring.
- No `standalone_otel.rs`.
- No standalone docs/tests.

### Tests
- Extended `network_policy.rs` tests for event mapping, metadata
propagation, fallbacks, timestamp format, and target prefix.
- Extended HTTP tests to assert unix-socket deny block audit events.
- Extended SOCKS tests to cover deny emission from handler deny
branches.
- Added/updated core tests to verify audit metadata threading into
managed proxy state.

### Validation run
- `just fmt`
- `cargo test -p codex-network-proxy` 
- `cargo test -p codex-core` ran with one unrelated flaky timeout
(`shell_snapshot::tests::snapshot_shell_does_not_inherit_stdin`), and
the test passed when rerun directly 

---------

Co-authored-by: viyatb-oai <viyatb@openai.com>
2026-02-25 11:46:37 -05:00
jif-oai
8362b79cb4 feat: fix sqlite home (#12787) 2026-02-25 15:52:55 +00:00
jif-oai
01f25a7b96 chore: unify max depth parameter (#12770)
Users were confused
2026-02-25 15:20:24 +00:00
mcgrew-oai
bccce0d75f otel: add host.name resource attribute to logs/traces via gethostname (#12352)
**PR Summary**

This PR adds the OpenTelemetry `host.name` resource attribute to Codex
OTEL exports so every OTEL log (and trace, via the shared resource)
carries the machine hostname.

**What changed**

- Added `host.name` to the shared OTEL `Resource` in
`/Users/michael.mcgrew/code/codex/codex-rs/otel/src/otel_provider.rs`
  - This applies to both:
    - OTEL logs (`SdkLoggerProvider`)
    - OTEL traces (`SdkTracerProvider`)
- Hostname is now resolved via `gethostname::gethostname()`
(best-effort)
  - Value is trimmed
  - Empty values are omitted (non-fatal)
- Added focused unit tests for:
  - including `host.name` when present
  - omitting `host.name` when missing/empty

**Why**

- `host.name` is host/process metadata and belongs on the OTEL
`resource`, not per-event attributes.
- Attaching it in the shared resource is the smallest change that
guarantees coverage across all exported OTEL logs/traces.

**Scope / Non-goals**

- No public API changes
- No changes to metrics behavior (this PR only updates log/trace
resource metadata)

**Dependency updates**

- Added `gethostname` as a workspace dependency and `codex-otel`
dependency
- `Cargo.lock` updated accordingly
- `MODULE.bazel.lock` unchanged after refresh/check

**Validation**

- `just fmt`
- `cargo test -p codex-otel`
- `just bazel-lock-update`
- `just bazel-lock-check`
2026-02-25 09:54:45 -05:00
jif-oai
8d49e0d0c4 nit: migration (#12772) 2026-02-25 13:56:52 +00:00
jif-oai
e4bfa763f6 feat: record memory usage (#12761) 2026-02-25 13:48:40 +00:00
jif-oai
5441130e0a feat: adding stream parser (#12666)
Add a stream parser to extract citations (and others) from a stream.
This support cases where markers are split in differen tokens.

Codex never manage to make this code work so everything was done
manually. Please review correctly and do not touch this part of the code
without a very clear understanding of it
2026-02-25 13:27:58 +00:00
jif-oai
5a9a5b51b2 feat: add large stack test macro (#12768)
This PR adds the macro `#[large_stack_test]`

This spawns the tests in a dedicated tokio runtime with a larger stack.
It is useful for tests that needs the full recursion on the harness
(which is now too deep for windows for example)
2026-02-25 13:19:21 +00:00
jif-oai
bcd6e68054 Display pending child-thread approvals in TUI (#12767)
Summary
- propagate approval policy from parent to spawned agents and drop the
Never override so sub-agents respect the caller’s request
- refresh the pending-approval list whenever events arrive or the active
thread changes and surface the list above the composer for inactive
threads
- add widgets, helpers, and tests covering the new pending-thread
approval UI state

![Uploading Screenshot 2026-02-25 at 11.02.18.png…]()
2026-02-25 11:40:11 +00:00
Michael Bolin
93efcfd50d feat: record whether a skill script is approved for the session (#12756)
## Why

`unix_escalation.rs` checks a session-scoped approval cache before
prompting again for an execve-intercepted skill script. Without also
recording `ReviewDecision::ApprovedForSession`, that cache never gets
populated, so the same skill script can still trigger repeated approval
prompts within one session.

## What Changed

- Add `execve_session_approvals` to `SessionServices` so the session can
track approved skill script paths.
- Record the script path when a skill-script prompt returns
`ReviewDecision::ApprovedForSession`, but only for the skill-script path
rather than broader prefix-rule approvals.
- Reuse the cached approval on later execve callbacks by treating an
already-approved skill script as `Decision::Allow`.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/12756).
* #12758
* __->__ #12756
2026-02-25 10:17:22 +00:00
alexsong-oai
6d6570d89d Support external agent config detect and import (#12660)
Migration Behavior

* Config
  *  Migrates settings.json into config.toml
* Only adds fields when config.toml is missing, or when those fields are
missing from the existing file
  *  Supported mappings:
    env -> shell_environment_policy
     sandbox.enabled = true -> sandbox_mode = "workspace-write"

* Skills
  *  Copies home and repo .claude/skills into .agents/skills
  *  Existing skill directories are not overwritten
  *  SKILL.md content is rewritten from Claude-related terms to Codex

* AgentsMd
  *  Repo only
  *  Migrates CLAUDE.md into AGENTS.md
* Detect/import only proceed when AGENTS.md is missing or present but
empty
  *  Content is rewritten from Claude-related terms to Codex
2026-02-25 02:11:51 -08:00
jif-oai
f46b767b7e feat: add search term to thread list (#12578)
Add `searchTerm` to `thread/list` that will search for a match in the
titles (the condition being `searchTerm` $$\in$$ `title`)
2026-02-25 09:59:41 +00:00
jif-oai
a046849438 fix: flaky test due to second-resolution for thread ordering (#12692) 2026-02-25 09:59:25 +00:00
jif-oai
10c04e11b8 feat: add service name to app-server (#12319)
Add service name to the app-server so that the app can use it's own
service name

This is on thread level because later we might plan the app-server to
become a singleton on the computer
2026-02-25 09:51:42 +00:00
Michael Bolin
6b3130f2e7 merge commit for archive created by Sapling 2026-02-25 01:47:46 -08:00
Michael Bolin
5dc9cb3458 feat: include availableDecisions with command approvals 2026-02-25 01:47:38 -08:00