Commit Graph

8634 Commits

Author SHA1 Message Date
jif-oai
bc6d9ef6fc feat: only source shell snapshot if the file exists (#9197) 2026-01-14 01:28:25 -08:00
jif-oai
dc3deaa3e7 feat: return an error if the image sent by the user is a bad image (#9146)
## Before
When we detect an `InvalidImageRequest`, we replace the image by a
placeholder and keep going

## Now
In such `InvalidImageRequest`, we check if the image is due to a user
message or a tool call output. For tool call output we still replace it
with a placeholder to avoid breaking the agentic loop bu tif this is
because of a user message, we send an error to the user
2026-01-14 09:07:45 +00:00
jif-oai
6fbb89e858 fix: shell snapshot clean-up (#9155)
Clean all shell snapshot files corresponding to sessions that have not
been updated in 7 days
Those files should never leak. The only known cases were it can leak are
during non graceful interrupt of the process (`kill -9, `panic`, OS
crash, ...)
2026-01-14 09:05:46 +00:00
jif-oai
258fc4b401 feat: add sourcing of rc files to shell snapshot (#9150) 2026-01-14 08:58:10 +00:00
Ahmed Ibrahim
b9ff4ec830 change api default model (#9188) 2026-01-13 22:33:34 -08:00
Michael Bolin
0c09dc3c03 feat: add threadId to MCP server messages (#9192)
This favors `threadId` instead of `conversationId` so we use the same
terms as https://developers.openai.com/codex/sdk/.

To test the local build:

```
cd codex-rs
cargo build --bin codex
npx -y @modelcontextprotocol/inspector ./target/debug/codex mcp-server
```

I sent:

```json
{
  "method": "tools/call",
  "params": {
    "name": "codex",
    "arguments": {
      "prompt": "favorite ls option?"
    },
    "_meta": {
      "progressToken": 0
    }
  }
}
```

and got:

```json
{
  "content": [
    {
      "type": "text",
      "text": "`ls -lah` (or `ls -alh`) — long listing, includes dotfiles, human-readable sizes."
    }
  ],
  "structuredContent": {
    "threadId": "019bbb20-bff6-7130-83aa-bf45ab33250e"
  }
}
```

and successfully used the `threadId` in the follow-up with the
`codex-reply` tool call:

```json
{
  "method": "tools/call",
  "params": {
    "name": "codex-reply",
    "arguments": {
      "prompt": "what is the long versoin",
      "threadId": "019bbb20-bff6-7130-83aa-bf45ab33250e"
    },
    "_meta": {
      "progressToken": 1
    }
  }
}
```

whose response also has the `threadId`:

```json
{
  "content": [
    {
      "type": "text",
      "text": "Long listing is `ls -l` (adds permissions, owner/group, size, timestamp)."
    }
  ],
  "structuredContent": {
    "threadId": "019bbb20-bff6-7130-83aa-bf45ab33250e"
  }
}
```

Fixes https://github.com/openai/codex/issues/3712.
2026-01-13 22:14:41 -08:00
Michael Bolin
72ea59f913 Merge f4af072751 into sapling-pr-archive-bolinfest 2026-01-13 21:59:58 -08:00
Michael Bolin
f4af072751 feat: add conversationId to MCP server messages 2026-01-13 21:59:54 -08:00
Michael Bolin
494119e754 merge commit for archive created by Sapling 2026-01-13 21:58:39 -08:00
Michael Bolin
0499d0cf7a feat: add conversationId to MCP server messages 2026-01-13 21:58:33 -08:00
Michael Bolin
7d5527fa7d merge commit for archive created by Sapling 2026-01-13 21:38:05 -08:00
Michael Bolin
0682e780cd feat: add conversationId to MCP server messages 2026-01-13 21:37:50 -08:00
sayan-oai
5675af5190 chore: clarify default shell for unified_exec (#8997)
The description of the `shell` arg for `exec_command` states the default
is `/bin/bash`, but AFAICT it's the user's default shell.

Default logic
[here](2a06d64bc9/codex-rs/core/src/tools/handlers/unified_exec.rs (L123)).

EDIT: #9004 has an alternative where we inform the model of the default
shell itself.
2026-01-13 21:37:41 -08:00
Michael Bolin
903aee676f merge commit for archive created by Sapling 2026-01-13 21:19:41 -08:00
Michael Bolin
80aabc4232 feat: add conversationId to MCP server messages 2026-01-13 21:19:09 -08:00
Michael Bolin
f0992273e4 merge commit for archive created by Sapling 2026-01-13 21:13:34 -08:00
Michael Bolin
697e3a5ff5 feat: add conversationId to MCP server messages 2026-01-13 21:13:27 -08:00
Michael Bolin
3e682cc4eb Merge 6b5ba1fd92 into sapling-pr-archive-bolinfest 2026-01-13 21:12:15 -08:00
Michael Bolin
6b5ba1fd92 feat: add conversationId to MCP server messages 2026-01-13 21:10:08 -08:00
Eric Traut
31d9b6f4d2 Improve handling of config and rules errors for app server clients (#9182)
When an invalid config.toml key or value is detected, the CLI currently
just quits. This leaves the VSCE in a dead state.

This PR changes the behavior to not quit and bubble up the config error
to users to make it actionable. It also surfaces errors related to
"rules" parsing.

This allows us to surface these errors to users in the VSCE, like this:

<img width="342" height="129" alt="Screenshot 2026-01-13 at 4 29 22 PM"
src="https://github.com/user-attachments/assets/a79ffbe7-7604-400c-a304-c5165b6eebc4"
/>

<img width="346" height="244" alt="Screenshot 2026-01-13 at 4 45 06 PM"
src="https://github.com/user-attachments/assets/de874f7c-16a2-4a95-8c6d-15f10482e67b"
/>
2026-01-13 17:57:09 -08:00
Ahmed Ibrahim
5a82a72d93 Use offline cache for tui migrations (#9186) 2026-01-13 17:44:12 -08:00
Josh McKinney
ce49e92848 fix(tui): harden paste-burst state transitions (#9124)
User-facing symptom: On terminals that deliver pastes as rapid
KeyCode::Char/Enter streams (notably Windows), paste-burst transient
state
can leak into the next input. Users can see Enter insert a newline when
they meant to submit, or see characters appear late / handled through
the
wrong path.

System problem: PasteBurst is time-based. Clearing only the
classification window (e.g. via clear_window_after_non_char()) can erase
last_plain_char_time without emitting buffered text. If a buffer is
still
non-empty after that, flush_if_due() no longer has a timeout clock to
flush against, so the buffer can get "stuck" until another plain char
arrives.

This was surfaced while adding deterministic regression tests for
paste-burst behavior.

Fix: when disabling burst detection, defuse any in-flight burst state:
flush held/buffered text through handle_paste() (so it follows normal
paste integration), then clear timing and Enter suppression.

Document the rationale inline and update docs/tui-chat-composer.md so
"disable_paste_burst" matches the actual behavior.
2026-01-14 01:42:21 +00:00
Michael Bolin
9e54867c79 Merge b99319787f into sapling-pr-archive-bolinfest 2026-01-13 17:25:06 -08:00
Michael Bolin
b99319787f fix: prefer PathBuf to String for ParsePolicy::path field 2026-01-13 17:25:01 -08:00
Ahmed Ibrahim
4d787a2cc2 Renew cache ttl on etag match (#9174)
so we don't do unnecessary fetches
2026-01-14 01:21:41 +00:00
Ahmed Ibrahim
c96c26cf5b [CODEX-4427] improve parsed commands (#8933)
**make command summaries more accurate by distinguishing
list/search/read operations across common CLI tools.**
- Added parsing helpers to centralize operand/flag handling (cd_target,
sed_read_path, first_non_flag_operand, single_non_flag_operand,
parse_grep_like, awk_data_file_operand, python_walks_files,
is_python_command) and reused them in summarize_main_tokens/shell
parsing.
- Newly parsed list-files commands: git ls-files, rg --files (incl.
rga/ripgrep-all), eza/exa, tree, du, python -c file-walks, plus fd/find
map to ListFiles when no query.
- Newly parsed search commands: git grep, grep/egrep/fgrep, ag/ack/pt,
rg/rga files-with-matches flags (-l/-L, --files-with-matches,
--files-without-match), with improved flag skipping to avoid
misclassifying args as paths.
- Newly parsed read commands: bat/batcat, less, more, awk <file>, and
more flexible sed -n range + file detection.
- refine “small formatting command” detection for awk/sed, handle cd
with -- or multiple operands, keep pipeline summaries focused on primary
command.
2026-01-13 16:59:33 -08:00
Ahmed Ibrahim
7e33ac7eb6 clean models manager (#9168)
Have only the following Methods:
- `list_models`: getting current available models
- `try_list_models`: sync version no refresh for tui use
- `get_default_model`: get the default model (should be tightened to
core and received on session configuration)
- `get_model_info`: get `ModelInfo` for a specific model (should be
tightened to core but used in tests)
- `refresh_if_new_etag`: trigger refresh on different etags

Also move the cache to its own struct
2026-01-13 16:55:33 -08:00
github-actions[bot]
ebbbee70c6 Update models.json (#9136)
Automated update of models.json.

Co-authored-by: aibrahim-oai <219906144+aibrahim-oai@users.noreply.github.com>
2026-01-13 16:46:24 -08:00
pakrym-oai
5a70b1568f WebSocket test server script (#9175)
Very simple test server to test Responses API WebSocket transport
integration.
2026-01-13 16:21:14 -08:00
Michael Bolin
903a0c0933 feat: add bazel-codex entry to justfile (#9177)
This is less straightforward than I realized, so created an entry for
this in our `justfile`.

Verified that running `just bazel-codex` from anywhere in the repo uses
the user's `$PWD` as the one to run Codex.

While here, updated the `MODULE.bazel.lock`, though it looks like I need
to add a CI job that runs `bazel mod deps --lockfile_mode=error` or
something.
2026-01-13 16:16:22 -08:00
Michael Bolin
ec5f89ecf8 merge commit for archive created by Sapling 2026-01-13 16:11:07 -08:00
Michael Bolin
2cf5621f15 feat: add bazel-codex entry to justfile 2026-01-13 16:11:01 -08:00
Michael Bolin
5cf1b2adc9 merge commit for archive created by Sapling 2026-01-13 16:10:11 -08:00
Michael Bolin
17a7ac0449 feat: add bazel-codex entry to justfile 2026-01-13 16:10:02 -08:00
Michael Bolin
376186be98 Merge 7a2f62edb8 into sapling-pr-archive-bolinfest 2026-01-13 15:53:33 -08:00
Michael Bolin
7a2f62edb8 feat: add bazel-codex entry to justfile 2026-01-13 15:53:26 -08:00
Michael Bolin
4c673086bc fix: integration test for #9011 (#9166)
Adds an integration test for the new behavior introduced in
https://github.com/openai/codex/pull/9011. The work to create the test
setup was substantial enough that I thought it merited a separate PR.

This integration test spawns `codex` in TUI mode, which requires
spawning a PTY to run successfully, so I had to introduce quite a bit of
scaffolding in `run_codex_cli()`. I was surprised to discover that we
have not done this in our codebase before, so perhaps this should get
moved to a common location so it can be reused.

The test itself verifies that a malformed `rules` in `$CODEX_HOME`
prints a human-readable error message and exits nonzero.
2026-01-13 23:39:34 +00:00
Michael Bolin
64a640b785 Merge 904c88da7b into sapling-pr-archive-bolinfest 2026-01-13 15:33:12 -08:00
Michael Bolin
904c88da7b fix: Prefer raw strings (r#) where appropriate, particularly in tests.
Updated AGENTS.md to memorialize this practice.
2026-01-13 15:32:35 -08:00
Michael Bolin
ea6e0c4335 merge commit for archive created by Sapling 2026-01-13 15:23:19 -08:00
Michael Bolin
34be9ecca6 fix: integration test for #9011 2026-01-13 15:22:29 -08:00
Michael Bolin
2cd1a0a45e fix: report an appropriate error in the TUI for malformed rules (#9011)
The underlying issue is that when we encountered an error starting a
conversation (any sort of error, though making `$CODEX_HOME/rules` a
file rather than folder was the example in #8803), then we were writing
the message to stderr, but this could be printed over by our UI
framework so the user would not see it. In general, we disallow the use
of `eprintln!()` in this part of the code for exactly this reason,
though this was suppressed by an `#[allow(clippy::print_stderr)]`.

This attempts to clean things up by changing `handle_event()` and
`handle_tui_event()` to return a `Result<AppRunControl>` instead of a
`Result<bool>`, which is a new type introduced in this PR (and depends
on `ExitReason`, also a new type):

```rust
#[derive(Debug)]
pub(crate) enum AppRunControl {
    Continue,
    Exit(ExitReason),
}

#[derive(Debug, Clone)]
pub enum ExitReason {
    UserRequested,
    Fatal(String),
}
```

This makes it possible to exit the primary control flow of the TUI with
richer information. This PR adds `ExitReason` to the existing
`AppExitInfo` struct and updates `handle_app_exit()` to print the error
and exit code `1` in the event of `ExitReason::Fatal`.

I tried to create an integration test for this, but it was a bit
involved, so I published it as a separate PR:
https://github.com/openai/codex/pull/9166. For this PR, please have
faith in my manual testing!

Fixes https://github.com/openai/codex/issues/8803.




---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/9011).
* #9166
* __->__ #9011
2026-01-13 23:21:32 +00:00
pakrym-oai
9f8d3c14ce Fix flakiness in WebSocket tests (#9169)
The connection was being added to the list after the WebSocket response
was sent.

So the test can sometimes race and observe connections before the list
was updated.

After this change, connection and request is added to the list before
the response is sent.
2026-01-13 15:09:59 -08:00
xl-openai
89403c5e11 Allow close skill popup with esc. (#9165)
<img width="398" height="133" alt="image"
src="https://github.com/user-attachments/assets/3084e793-ce5b-4f92-ad60-4c73e65c21c5"
/>
<img width="242" height="86" alt="image"
src="https://github.com/user-attachments/assets/57dd5587-0aea-4a55-91b8-273702939cb2"
/>

You can now esc to quit the skill popup and submit the input as it is.
2026-01-13 15:02:44 -08:00
Michael Bolin
53e09ac55a merge commit for archive created by Sapling 2026-01-13 14:41:56 -08:00
Michael Bolin
b95623e031 fix: integration test for #9011 2026-01-13 14:41:31 -08:00
Michael Bolin
de88da3dd3 fix: report an appropriate error in the TUI for malformed rules 2026-01-13 14:41:02 -08:00
Michael Bolin
48f601bbec Merge 67ca792915 into sapling-pr-archive-bolinfest 2026-01-13 14:22:49 -08:00
Michael Bolin
67ca792915 fix: integration test for #9011 2026-01-13 14:22:42 -08:00
Michael Bolin
7736609e73 Merge e6d8dff7b2 into sapling-pr-archive-bolinfest 2026-01-13 14:14:12 -08:00