Commit Graph

648 Commits

Author SHA1 Message Date
Michael Bolin
e12cf808b5 merge commit for archive created by Sapling 2025-05-04 08:48:37 -07:00
Michael Bolin
72b1d3ad57 feat: make cwd a required field of Config so we stop assuming std::env::current_dir() in a session 2025-05-04 08:48:32 -07:00
Michael Bolin
c2806574cb merge commit for archive created by Sapling 2025-05-04 08:43:54 -07:00
Michael Bolin
15bc38585c feat: make cwd a required field of Config so we stop assuming std::env::current_dir() in a session 2025-05-04 08:43:49 -07:00
Michael Bolin
66a2153d4f Merge 3f73058676 into sapling-pr-archive-bolinfest 2025-05-03 13:52:15 -07:00
Michael Bolin
3f73058676 feat: make cwd a required field of Config so we stop assuming std::env::current_dir() in a session 2025-05-03 13:52:06 -07:00
Michael Bolin
717dac4690 Merge da049df255 into sapling-pr-archive-bolinfest 2025-05-03 12:31:08 -07:00
Michael Bolin
da049df255 feat: drop support for q since we already support ctrl+d 2025-05-03 12:30:58 -07:00
Andrey Mishchenko
4b61fb8bab use "Title case" in README.md (#798) 2025-05-03 10:17:44 -07:00
Michael Bolin
0442458309 doc: update the config.toml documentation for the Rust CLI in codex-rs/README.md (#795)
https://github.com/openai/codex/pull/793 had important information on
the `notify` config option that seemed worth memorializing, so this PR
updates the documentation about all of the configurable options in
`~/.codex/config.toml`.
2025-05-02 20:32:24 -07:00
Michael Bolin
7c7b55e7c9 merge commit for archive created by Sapling 2025-05-02 20:30:23 -07:00
Michael Bolin
cbd97f54e5 doc: update the config.toml documentation for the Rust CLI in codex-rs/README.md 2025-05-02 20:30:18 -07:00
Michael Bolin
a001909243 merge commit for archive created by Sapling 2025-05-02 20:29:23 -07:00
Michael Bolin
630880e379 doc: update the config.toml documentation for the Rust CLI in codex-rs/README.md 2025-05-02 20:29:18 -07:00
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