Skip to content
This repository was archived by the owner on Oct 1, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,13 @@ turn's `exec resume` command.
`:dangerously_bypass_approvals_and_sandbox`, `:skip_git_repo_check`,
`:ephemeral`,
`:config_overrides`, `:enabled_features`, `:disabled_features`,
`:images`
`:images`, `:output_schema`

These settings are forwarded on fresh and resumed turns. Sandbox and
approval policy become supported `-c` overrides on resume.
`:working_dir` / `:cwd` remains the subprocess directory on both turns.
Options that the resume command cannot preserve (`:cd`, `:add_dirs`,
`:search`, `:output_schema`) fail at session startup with
`:search`) fail at session startup with
`{:error, {:unsupported_resume_option, option}}`.

**Backend-only:**
Expand Down
15 changes: 11 additions & 4 deletions lib/gen_agent/backends/codex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule GenAgent.Backends.Codex do
@moduledoc """
`GenAgent.Backend` implementation backed by `CodexWrapper`.

CodexWrapper 0.5.2 streams NDJSON while closing CLI stdin. This
CodexWrapper 0.5.3 streams NDJSON while closing CLI stdin. This
backend forwards translated events as they arrive, so
`handle_stream_event/2` can observe progress during a turn.

Expand Down Expand Up @@ -34,10 +34,10 @@ defmodule GenAgent.Backends.Codex do
`:dangerously_bypass_approvals_and_sandbox`, `:skip_git_repo_check`,
`:ephemeral`,
`:config_overrides`, `:enabled_features`, `:disabled_features`,
`:images`
`:images`, `:output_schema`

Options that cannot be preserved on `exec resume` (`:cd`,
`:add_dirs`, `:search`, `:output_schema`) are rejected by
`:add_dirs`, `:search`) are rejected by
`start_session/1`. Use `:working_dir` / `:cwd` for a directory that
persists across turns. Session options are translated into supported
resume arguments; `:sandbox` and `:approval_policy` use config
Expand Down Expand Up @@ -71,7 +71,8 @@ defmodule GenAgent.Backends.Codex do
:config_overrides,
:enabled_features,
:disabled_features,
:images
:images,
:output_schema
]

defstruct [
Expand Down Expand Up @@ -186,6 +187,9 @@ defmodule GenAgent.Backends.Codex do
{:images, v}, e ->
Enum.reduce(v, e, &Exec.image(&2, &1))

{:output_schema, v}, e ->
Exec.output_schema(e, v)

_other, e ->
e
end)
Expand Down Expand Up @@ -229,6 +233,9 @@ defmodule GenAgent.Backends.Codex do
{:images, values}, r ->
Enum.reduce(values, r, &ExecResume.image(&2, &1))

{:output_schema, value}, r ->
ExecResume.output_schema(r, value)

_other, r ->
r
end)
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ defmodule GenAgentCodex.MixProject do
defp deps do
[
{:gen_agent, "~> 0.2.0"},
{:codex_wrapper, "~> 0.5.2"},
{:codex_wrapper, "~> 0.5.3"},
{:ex_doc, "~> 0.35", only: :dev, runtime: false},
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}
Expand Down
2 changes: 1 addition & 1 deletion mix.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
%{
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"codex_wrapper": {:hex, :codex_wrapper, "0.5.2", "8c91e2972e0055cf437f3fbc9ac4842a41dd5c073a575c02c41cea570fe47a74", [:mix], [{:forcola, "~> 0.3.5", [hex: :forcola, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c58693fc249decc101f71b1aee7d30d5bdb64b072729ffc7548a66f8aa7d75e6"},
"codex_wrapper": {:hex, :codex_wrapper, "0.5.3", "278806a6a0e4b91a6ac5398edcfc3524162f2220e2ee85917cd12bb0ecef747a", [:mix], [{:forcola, "~> 0.3.5", [hex: :forcola, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a93b0a27b2520e34fc5d90d91c208509ed4081fa678c7f0af25750f90893d9a7"},
"credo": {:hex, :credo, "1.7.19", "cc52129665fc7c15143d47838fda0f9cd6dac9ceced7bf4da6f85fcbfe64b12a", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "2d8bc95d5a7bb99dd2613621d4f08c6a3575c3fd4b62e6a2b48a100352a557b8"},
"dialyxir": {:hex, :dialyxir, "1.4.8", "7ef671a8aff9948b091d8c30f09467fbb16e77305cda451bce48109a0f5e021c", [:mix], [{:erlex, ">= 0.2.8", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "cbd5a851571e5dfeb32aaf2e840bfa98b7864cb3071bf2ef5d95d1276b12e072"},
"earmark_parser": {:hex, :earmark_parser, "1.4.46", "67607a0532e810c6f630a515c548d0b24949643f168cc556303bee4cf96105c7", [:mix], [], "hexpm", "9c44636e8a1c68c62f526b2dcd85d941dbbcee7ab82cf64ba06ce28bef8e89f5"},
Expand Down
9 changes: 9 additions & 0 deletions test/gen_agent/backends/codex_executable_conformance_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ defmodule GenAgent.Backends.CodexExecutableConformanceTest do
enabled_features: ["fixture_feature"],
disabled_features: ["other_feature"],
images: ["/fixture/image.png"],
output_schema: "/fixture/response.json",
env: [{"GEN_AGENT_FIXTURE", "configured"}]
)

Expand Down Expand Up @@ -120,6 +121,10 @@ defmodule GenAgent.Backends.CodexExecutableConformanceTest do
assert "fixture-model" in fresh_args
assert "read-only" in fresh_args
assert "first prompt" == List.last(fresh_args)

assert Enum.chunk_every(fresh_args, 2, 1, :discard)
|> Enum.member?(["--output-schema", "/fixture/response.json"])

assert File.read!(Path.join(context.directory, "fresh.env")) == "configured\n"

assert {:ok, second} = GenAgent.ask(name, "follow-up prompt")
Expand All @@ -133,6 +138,10 @@ defmodule GenAgent.Backends.CodexExecutableConformanceTest do
assert "fixture_feature" in resume_args
assert "other_feature" in resume_args
assert "/fixture/image.png" in resume_args

assert Enum.chunk_every(resume_args, 2, 1, :discard)
|> Enum.member?(["--output-schema", "/fixture/response.json"])

assert "follow-up prompt" == List.last(resume_args)
assert Enum.any?(resume_args, &String.contains?(&1, "approval_policy"))
assert Enum.any?(resume_args, &String.contains?(&1, "mcp_servers.fixture.enabled=false"))
Expand Down
2 changes: 1 addition & 1 deletion test/gen_agent/backends/codex_streaming_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ defmodule GenAgent.Backends.CodexStreamingTest do
end

test "options that cannot be preserved on resume fail at startup" do
for option <- [:cd, :add_dirs, :search, :output_schema] do
for option <- [:cd, :add_dirs, :search] do
assert {:error, {:unsupported_resume_option, ^option}} =
Codex.start_session([{option, "fixture"}])
end
Expand Down
Loading