Commit Graph

8634 Commits

Author SHA1 Message Date
Michael Bolin
84c0b0c589 Merge dfa0c64528 into sapling-pr-archive-bolinfest 2025-05-02 20:27:14 -07:00
Michael Bolin
dfa0c64528 doc: update the config.toml documentation for the Rust CLI in codex-rs/README.md 2025-05-02 20:27:06 -07:00
Michael Bolin
a180ed44e8 feat: configurable notifications in the Rust CLI (#793)
With this change, you can specify a program that will be executed to get
notified about events generated by Codex. The notification info will be
packaged as a JSON object. The supported notification types are defined
by the `UserNotification` enum introduced in this PR. Initially, it
contains only one variant, `AgentTurnComplete`:

```rust
pub(crate) enum UserNotification {
    #[serde(rename_all = "kebab-case")]
    AgentTurnComplete {
        turn_id: String,

        /// Messages that the user sent to the agent to initiate the turn.
        input_messages: Vec<String>,

        /// The last message sent by the assistant in the turn.
        last_assistant_message: Option<String>,
    },
}
```

This is intended to support the common case when a "turn" ends, which
often means it is now your chance to give Codex further instructions.

For example, I have the following in my `~/.codex/config.toml`:

```toml
notify = ["python3", "/Users/mbolin/.codex/notify.py"]
```

I created my own custom notifier script that calls out to
[terminal-notifier](https://github.com/julienXX/terminal-notifier) to
show a desktop push notification on macOS. Contents of `notify.py`:

```python
#!/usr/bin/env python3

import json
import subprocess
import sys


def main() -> int:
    if len(sys.argv) != 2:
        print("Usage: notify.py <NOTIFICATION_JSON>")
        return 1

    try:
        notification = json.loads(sys.argv[1])
    except json.JSONDecodeError:
        return 1

    match notification_type := notification.get("type"):
        case "agent-turn-complete":
            assistant_message = notification.get("last-assistant-message")
            if assistant_message:
                title = f"Codex: {assistant_message}"
            else:
                title = "Codex: Turn Complete!"
            input_messages = notification.get("input_messages", [])
            message = " ".join(input_messages)
            title += message
        case _:
            print(f"not sending a push notification for: {notification_type}")
            return 0

    subprocess.check_output(
        [
            "terminal-notifier",
            "-title",
            title,
            "-message",
            message,
            "-group",
            "codex",
            "-ignoreDnD",
            "-activate",
            "com.googlecode.iterm2",
        ]
    )

    return 0


if __name__ == "__main__":
    sys.exit(main())
```

For reference, here are related PRs that tried to add this functionality
to the TypeScript version of the Codex CLI:

* https://github.com/openai/codex/pull/160
* https://github.com/openai/codex/pull/498
codex-rs-5915a59c8290765d6097caf4074aae93a85380fa-1-rust-v0.0.2505021951
2025-05-02 19:48:13 -07:00
Michael Bolin
2cee8b914e Merge 68a493930a into sapling-pr-archive-bolinfest 2025-05-02 19:37:33 -07:00
Michael Bolin
68a493930a feat: add support for notifications 2025-05-02 19:37:27 -07:00
Michael Bolin
21cd953dbd feat: introduce mcp-server crate (#792)
This introduces the `mcp-server` crate, which contains a barebones MCP
server that provides an `echo` tool that echoes the user's request back
to them.

To test it out, I launched
[modelcontextprotocol/inspector](https://github.com/modelcontextprotocol/inspector)
like so:

```
mcp-server$ npx @modelcontextprotocol/inspector cargo run --
```

and opened up `http://127.0.0.1:6274` in my browser:


![image](https://github.com/user-attachments/assets/83fc55d4-25c2-4497-80cd-e9702283ff93)

I also had to make a small fix to `mcp-types`, adding
`#[serde(untagged)]` to a number of `enum`s.
2025-05-02 17:25:58 -07:00
Michael Bolin
8a14aedcc7 Merge 03323bbe75 into sapling-pr-archive-bolinfest 2025-05-02 16:59:41 -07:00
Michael Bolin
03323bbe75 feat: introduce mcp-server crate 2025-05-02 16:59:37 -07:00
Michael Bolin
d71452eb97 merge commit for archive created by Sapling 2025-05-02 16:44:32 -07:00
Michael Bolin
47d859b049 feat: introduce mcp-server crate 2025-05-02 16:44:27 -07:00
Michael Bolin
3c1171245f Merge 45c8623fe9 into sapling-pr-archive-bolinfest 2025-05-02 16:38:26 -07:00
Michael Bolin
45c8623fe9 feat: introduce mcp-server crate 2025-05-02 16:38:21 -07:00
Michael Bolin
865e518771 fix: mcp-types serialization wasn't quite working (#791)
While creating a basic MCP server in
https://github.com/openai/codex/pull/792, I discovered a number of bugs
with the initial `mcp-types` crate that I needed to fix in order to
implement the server.

For example, I discovered that when serializing a message, `"jsonrpc":
"2.0"` was not being included.

I changed the codegen so that the field is added as:

```rust
    #[serde(rename = "jsonrpc", default = "default_jsonrpc")]
    pub jsonrpc: String,
```

This ensures that the field is serialized as `"2.0"`, though the field
still has to be assigned, which is tedious. I may experiment with
`Default` or something else in the future. (I also considered creating a
custom serializer, but I'm not sure it's worth the trouble.)

While here, I also added `MCP_SCHEMA_VERSION` and `JSONRPC_VERSION` as
`pub const`s for the crate.

I also discovered that MCP rejects sending `null` for optional fields,
so I had to add `#[serde(skip_serializing_if = "Option::is_none")]` on
`Option` fields.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/791).
* #792
* __->__ #791
2025-05-02 16:38:05 -07:00
Michael Bolin
6d9298787e Merge d4538c333c into sapling-pr-archive-bolinfest 2025-05-02 16:30:06 -07:00
Michael Bolin
d4538c333c feat: introduce mcp-server crate 2025-05-02 16:29:57 -07:00
Michael Bolin
61825ccf25 Merge 97bdc586a4 into sapling-pr-archive-bolinfest 2025-05-02 16:09:23 -07:00
Michael Bolin
97bdc586a4 fix: ensure jsonrpc field is serialized as "2.0" 2025-05-02 16:09:01 -07:00
Michael Bolin
0d315104fe merge commit for archive created by Sapling 2025-05-02 15:29:44 -07:00
Michael Bolin
423ac7c7e9 fix: ensure jsonrpc field is serialized as "2.0" 2025-05-02 15:29:38 -07:00
Michael Bolin
3e9af0abb7 Merge 434d6ef892 into sapling-pr-archive-bolinfest 2025-05-02 15:05:29 -07:00
Michael Bolin
434d6ef892 fix: ensure jsonrpc field is serialized as "2.0" 2025-05-02 15:05:19 -07:00
Michael Bolin
2748894ca2 Merge 0a70ed663f into sapling-pr-archive-bolinfest 2025-05-02 15:04:35 -07:00
Michael Bolin
0a70ed663f fix: ensure jsonrpc field is serialized as "2.0" 2025-05-02 15:04:29 -07:00
Michael Bolin
3d0726109c merge commit for archive created by Sapling 2025-05-02 15:01:32 -07:00
Michael Bolin
c8f85b45e1 fix: ensure jsonrpc field is serialized as "2.0" 2025-05-02 14:39:00 -07:00
Michael Bolin
83961e0299 feat: introduce mcp-types crate (#787)
This adds our own `mcp-types` crate to our Cargo workspace. We vendor in
the
[`2025-03-26/schema.json`](05f2045136/schema/2025-03-26/schema.json)
from the MCP repo and introduce a `generate_mcp_types.py` script to
codegen the `lib.rs` from the JSON schema.

Test coverage is currently light, but I plan to refine things as we
start making use of this crate.

And yes, I am aware that
https://github.com/modelcontextprotocol/rust-sdk exists, though the
published https://crates.io/crates/rmcp appears to be a competing
effort. While things are up in the air, it seems better for us to
control our own version of this code.

Incidentally, Codex did a lot of the work for this PR. I told it to
never edit `lib.rs` directly and instead to update
`generate_mcp_types.py` and then re-run it to update `lib.rs`. It
followed these instructions and once things were working end-to-end, I
iteratively asked for changes to the tests until the API looked
reasonable (and the code worked). Codex was responsible for figuring out
what to do to `generate_mcp_types.py` to achieve the requested test/API
changes.
2025-05-02 13:33:14 -07:00
Michael Bolin
d045ce7ed7 merge commit for archive created by Sapling 2025-05-02 12:46:11 -07:00
Michael Bolin
48a15728e2 feat: introduce mcp-types crate 2025-05-02 12:46:04 -07:00
Michael Bolin
620871cc48 merge commit for archive created by Sapling 2025-05-02 12:37:49 -07:00
Michael Bolin
9bf3ab35ff feat: introduce mcp-types crate 2025-05-02 12:37:39 -07:00
Michael Bolin
53e395969e Merge 71ffb6df1b into sapling-pr-archive-bolinfest 2025-05-02 12:25:41 -07:00
Michael Bolin
71ffb6df1b feat: introduce mcp-types crate 2025-05-02 12:25:28 -07:00
anup-openai
f6b1ce2e3a Configure HTTPS agent for proxies (#775)
- Some workflows require you to route openAI API traffic through a proxy
- See
https://github.com/openai/openai-node/tree/v4?tab=readme-ov-file#configuring-an-https-agent-eg-for-proxies
for more details

---------

Co-authored-by: Thibault Sottiaux <tibo@openai.com>
Co-authored-by: Fouad Matin <fouad@openai.com>
2025-05-02 12:08:13 -07:00
Fouad Matin
b864cc3810 update: vite version (#766) 2025-05-02 09:30:08 -07:00
Michael Bolin
a4b51f6b67 feat: use Landlock for sandboxing on Linux in TypeScript CLI (#763)
Building on top of https://github.com/openai/codex/pull/757, this PR
updates Codex to use the Landlock executor binary for sandboxing in the
Node.js CLI. Note that Codex has to be invoked with either `--full-auto`
or `--auto-edit` to activate sandboxing. (Using `--suggest` or
`--dangerously-auto-approve-everything` ensures the sandboxing codepath
will not be exercised.)

When I tested this on a Linux host (specifically, `Ubuntu 24.04.1 LTS`),
things worked as expected: I ran Codex CLI with `--full-auto` and then
asked it to do `echo 'hello mbolin' into hello_world.txt` and it
succeeded without prompting me.

However, in my testing, I discovered that the sandboxing did *not* work
when using `--full-auto` in a Linux Docker container from a macOS host.
I updated the code to throw a detailed error message when this happens:


![image](https://github.com/user-attachments/assets/e5b99def-f00e-4ade-a0c5-2394d30df52e)
2025-05-01 12:34:56 -07:00
Michael Bolin
9db12eb5d2 merge commit for archive created by Sapling 2025-05-01 11:48:14 -07:00
Michael Bolin
3d5cdd3fd5 feat: use Landlock for sandboxing on Linux 2025-05-01 11:48:09 -07:00
Michael Bolin
9bc4fde11b merge commit for archive created by Sapling 2025-05-01 11:47:20 -07:00
Michael Bolin
a490029d67 feat: use Landlock for sandboxing on Linux 2025-05-01 11:47:14 -07:00
Michael Bolin
1acf0d0e24 merge commit for archive created by Sapling 2025-05-01 08:46:06 -07:00
Michael Bolin
96037168e9 feat: use Landlock for sandboxing on Linux 2025-05-01 08:46:01 -07:00
Michael Bolin
404ea5c299 Merge 1bc4eee899 into sapling-pr-archive-bolinfest 2025-05-01 08:36:29 -07:00
Michael Bolin
1bc4eee899 feat: use Landlock for sandboxing on Linux 2025-05-01 08:36:20 -07:00
Michael Bolin
3f5975ad5a chore: make build process a single script to run (#757)
This introduces `./codex-cli/scripts/stage_release.sh`, which is a shell
script that stages a release for the Node.js module in a temp directory.
It updates the release to include these native binaries:

```
bin/codex-linux-sandbox-arm64
bin/codex-linux-sandbox-x64
```

though this PR does not update Codex CLI to use them yet.

When doing local development, run
`./codex-cli/scripts/install_native_deps.sh` to install these in your
own `bin/` folder.

This PR also updates `README.md` to document the new workflow.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/757).
* #763
* __->__ #757
2025-05-01 08:36:07 -07:00
Fouad Matin
463a230991 bump(version): 0.1.2504301751 (#768)
## `0.1.2504301751`

### 🚀 Features

- User config api key (#569)
- `@mention` files in codex (#701)
- Add `--reasoning` CLI flag (#314)
- Lower default retry wait time and increase number of tries (#720)
- Add common package registries domains to allowed-domains list (#414)

### 🪲 Bug Fixes

- Insufficient quota message (#758)
- Input keyboard shortcut opt+delete (#685)
- `/diff` should include untracked files (#686)
- Only allow running without sandbox if explicitly marked in safe
container (#699)
- Tighten up check for /usr/bin/sandbox-exec (#710)
- Check if sandbox-exec is available (#696)
- Duplicate messages in quiet mode (#680)
2025-04-30 17:55:34 -07:00
Fouad Matin
985fd44ec0 fix: input keyboard shortcut opt+delete (#685) 2025-04-30 17:17:13 -07:00
Michael Bolin
e26bdaf006 merge commit for archive created by Sapling 2025-04-30 16:23:41 -07:00
Michael Bolin
07a6659814 feat: use Landlock for sandboxing on Linux 2025-04-30 16:23:35 -07:00
moppywhip
bc4e6db749 feat: @mention files in codex (#701)
Solves #700

## State of the World Before

Prior to this PR, when users wanted to share file contents with Codex,
they had two options:
- Manually copy and paste file contents into the chat
- Wait for the assistant to use the shell tool to view the file

The second approach required the assistant to:
1. Recognize the need to view a file
2. Execute a shell tool call
3. Wait for the tool call to complete
4. Process the file contents

This consumed extra tokens and reduced user control over which files
were shared with the model.

## State of the World After

With this PR, users can now:
- Reference files directly in their chat input using the `@path` syntax
- Have file contents automatically expanded into XML blocks before being
sent to the LLM

For example, users can type `@src/utils/config.js` in their message, and
the file contents will be included in context. Within the terminal chat
history, these file blocks will be collapsed back to `@path` format in
the UI for clean presentation.

Tag File suggestions:
<img width="857" alt="file-suggestions"
src="https://github.com/user-attachments/assets/397669dc-ad83-492d-b5f0-164fab2ff4ba"
/>

Tagging files in action:
<img width="858" alt="tagging-files"
src="https://github.com/user-attachments/assets/0de9d559-7b7f-4916-aeff-87ae9b16550a"
/>

Demo video of file tagging:
[![Demo video of file
tagging](https://img.youtube.com/vi/vL4LqtBnqt8/0.jpg)](https://www.youtube.com/watch?v=vL4LqtBnqt8)

## Implementation Details

This PR consists of 2 main components:

1. **File Tag Utilities**:
- New `file-tag-utils.ts` utility module that handles both expansion and
collapsing of file tags
- `expandFileTags()` identifies `@path` tokens and replaces them with
XML blocks containing file contents
- `collapseXmlBlocks()` reverses the process, converting XML blocks back
to `@path` format for UI display
- Tokens are only expanded if they point to valid files (directories are
ignored)
   - Expansion happens just before sending input to the model

2. **Terminal Chat Integration**:
- Leveraged the existing file system completion system for tabbing to
support the `@path` syntax
   - Added `updateFsSuggestions` helper to manage filesystem suggestions
- Added `replaceFileSystemSuggestion` to replace input with filesystem
suggestions
- Applied `collapseXmlBlocks` in the chat response rendering so that
tagged files are shown as simple `@path` tags

The PR also includes test coverage for both the UI and the file tag
utilities.

## Next Steps

Some ideas I'd like to implement if this feature gets merged:

- Line selection: `@path[50:80]` to grab specific sections of files
- Method selection: `@path#methodName` to grab just one function/class
- Visual improvements: highlight file tags in the UI to make them more
noticeable
2025-04-30 16:19:55 -07:00
Kevin Alwell
bd82101859 fix: insufficient quota message (#758)
This pull request includes a change to improve the error message
displayed when there is insufficient quota in the `AgentLoop` class. The
updated message provides more detailed information and a link for
managing or purchasing credits.

Error message improvement:

*
[`codex-cli/src/utils/agent/agent-loop.ts`](diffhunk://#diff-b15957eac2720c3f1f55aa32f172cdd0ac6969caf4e7be87983df747a9f97083L1140-R1140):
Updated the error message in the `AgentLoop` class to include the
specific error message (if available) and a link to manage or purchase
credits.


Fixes #751
2025-04-30 16:00:50 -07:00