diff --git a/lib/gen_agent/backends/codex.ex b/lib/gen_agent/backends/codex.ex index d328e69..2ec429f 100644 --- a/lib/gen_agent/backends/codex.ex +++ b/lib/gen_agent/backends/codex.ex @@ -2,7 +2,7 @@ defmodule GenAgent.Backends.Codex do @moduledoc """ `GenAgent.Backend` implementation backed by `CodexWrapper`. - CodexWrapper 0.5.1 streams NDJSON while closing CLI stdin. This + CodexWrapper 0.5.2 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. @@ -15,6 +15,12 @@ defmodule GenAgent.Backends.Codex do `update_session/2` then records it on the session struct, and the next turn is dispatched via `ExecResume` with that id. + `terminate_session/1` has no native process to close. GenAgent cancels + its prompt task on interrupt, watchdog, stop, or agent death, but the + default Port runner closes pipes without guaranteeing that the CLI and + its subprocesses have exited. Choose a runner with process-group + termination when OS-level settlement is required. + ## Options accepted by `start_session/1` Config-level (forwarded to `CodexWrapper.Config.new/1`): diff --git a/mix.exs b/mix.exs index ec33159..f337273 100644 --- a/mix.exs +++ b/mix.exs @@ -32,7 +32,7 @@ defmodule GenAgentCodex.MixProject do defp deps do [ {:gen_agent, "~> 0.2.0"}, - {:codex_wrapper, "~> 0.5.1"}, + {:codex_wrapper, "~> 0.5.2"}, {:ex_doc, "~> 0.35", only: :dev, runtime: false}, {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false} diff --git a/mix.lock b/mix.lock index 2163cd9..5568b2b 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,6 @@ %{ "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, - "codex_wrapper": {:hex, :codex_wrapper, "0.5.1", "1cdab3c3ef5ff1dc9ab0266501115885dd200e51e243629c05cad30b5e4e7759", [:mix], [{:forcola, "~> 0.3.4", [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", "419a776eae91df21090054eebf232e0a1b9413962521c99d69f2920e3c8bd2a0"}, + "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"}, "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"}, diff --git a/test/fixtures/codex_cli.sh b/test/fixtures/codex_cli.sh index 6f8510c..fa96c51 100644 --- a/test/fixtures/codex_cli.sh +++ b/test/fixtures/codex_cli.sh @@ -9,6 +9,7 @@ if [ "${2:-}" = "resume" ]; then fi printf '%s\n' "$@" > "$fixture_dir/$mode.args" +printf '%s\n' "${GEN_AGENT_FIXTURE-unset}" > "$fixture_dir/$mode.env" case "${*}" in *fail*) @@ -32,7 +33,7 @@ case "$fixture_mode" in printf '%s\n' '{"type":"thread.started","thread_id":"fixture-thread"}' printf '%s\n' '{"type":"item.completed","item":{"type":"agent_message","text":"partial"}}' sleep 2 - printf '%s\n' '{"type":"turn.completed"}' + printf '%s\n' '{"type":"turn.completed"}' 2>/dev/null || true ;; success) diff --git a/test/gen_agent/backends/codex_executable_conformance_test.exs b/test/gen_agent/backends/codex_executable_conformance_test.exs index e35c417..8b0d8dd 100644 --- a/test/gen_agent/backends/codex_executable_conformance_test.exs +++ b/test/gen_agent/backends/codex_executable_conformance_test.exs @@ -89,7 +89,8 @@ defmodule GenAgent.Backends.CodexExecutableConformanceTest do config_overrides: ["mcp_servers.fixture.enabled=false"], enabled_features: ["fixture_feature"], disabled_features: ["other_feature"], - images: ["/fixture/image.png"] + images: ["/fixture/image.png"], + env: [{"GEN_AGENT_FIXTURE", "configured"}] ) assert {:ok, first} = GenAgent.ask(name, "first prompt") @@ -119,6 +120,7 @@ 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 File.read!(Path.join(context.directory, "fresh.env")) == "configured\n" assert {:ok, second} = GenAgent.ask(name, "follow-up prompt") assert second.text == "fixture-resume" @@ -134,6 +136,7 @@ defmodule GenAgent.Backends.CodexExecutableConformanceTest do 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")) + assert File.read!(Path.join(context.directory, "resume.env")) == "configured\n" end test "terminal failure from the executable reaches GenAgent as an error", context do