Skip to content

Commit 52ef740

Browse files
committed
Release v0.4.4: App-server multi-modal inputs, exec CLI parity, typed deltas
This release closes significant parity gaps with the upstream Codex CLI and app-server protocol, adding multi-modal input support, comprehensive CLI flag forwarding, and typed event handling for previously raw notifications. App-server transport enhancements: - Thread.run/3 and run_streamed/3 now accept UserInput block lists containing text, image, and localImage types in addition to plain string input - Thread start/resume forwards model, model_provider, config, base_instructions, developer_instructions, and experimental_raw_events parameters - Codex.Options defaults for model and reasoning_effort are applied to app-server thread starts when not explicitly overridden - Sandbox policy accepts full structured format with type, writable_roots, network_access, exclude_tmpdir_env_var, and exclude_slash_tmp fields - Added command_write_stdin/4 for interactive terminal command input Typed app-server notifications: - ReasoningSummaryPartAdded for incremental reasoning summary updates - FileChangeOutputDelta for streaming file change apply-patch output - TerminalInteraction for interactive stdin write events - McpToolCallProgress for MCP tool execution progress messages - AccountUpdated, AccountRateLimitsUpdated, AccountLoginCompleted for auth state - McpServerOauthLoginCompleted for MCP OAuth flow completion - WindowsWorldWritableWarning for Windows security warnings - TurnCompleted now includes error field from turn.error payloads Exec CLI parity: - Added profile, oss, local_provider, full_auto, output_last_message, and color flags to thread options with proper CLI argument forwarding - Added dangerously_bypass_approvals_and_sandbox flag (mutually exclusive with full_auto) - Generic config_overrides field accepts string list or key/value pairs for arbitrary -c key=value overrides - Exec.review/2 and review_stream/2 run codex exec review with uncommitted, base_branch, commit, or custom prompt targets - Codex.resume_thread(:last) maps to codex exec resume --last Reasoning item fidelity: - Items.Reasoning now preserves summary and content as separate list fields - Text field is still populated by joining summary and content for backwards compatibility - ItemAdapter and Items.parse handle structured reasoning consistently Approval handling: - Approval hooks can return grant_root option to accept file-change approvals with the proposed root for the current session - ApprovalDecision encodes grant_root as acceptForSession response Bug fixes: - Streamed turn failures handle non-text final_response payloads without crashing by extracting error details from turn.error when present - Structured /new input blocks (single text block containing /new) properly reset conversation state for app-server and exec transport runs - Tool guardrail handler exceptions are caught and surfaced as GuardrailError instead of crashing the turn process - Approval hook exceptions are caught and surfaced as Error with kind approval_hook_failed - Progress telemetry metadata merge handles nil base metadata gracefully - Thread.Backoff clamps exponential delay to prevent integer overflow on high attempt counts - Tool call deduplication uses fallback key based on tool_name and arguments hash when call_id is nil Test coverage: - Added tests for multi-modal input handling in app-server transport - Added tests for structured /new reset behavior - Added tests for guardrail and approval hook exception handling - Added tests for exec CLI flag forwarding and review subcommand - Added tests for reasoning summary/content preservation - Added notification adapter tests for all new typed events - Added backoff overflow protection tests
1 parent 32cbb28 commit 52ef740

42 files changed

Lines changed: 8749 additions & 319 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.4.4] - 2025-12-29
9+
10+
### Added
11+
12+
- App-server `UserInput` list support for `Codex.Thread.run/3` and `run_streamed/3` (text/image/localImage)
13+
- Thread/turn app-server params for model/provider/config/instructions, sandbox_policy, and experimental raw events, with defaults for model + reasoning effort
14+
- Typed app-server notifications for reasoning summaries/deltas, command/file output deltas, terminal interaction, MCP progress, and account updates
15+
- Exec CLI parity flags (`--profile`, `--oss`, `--local-provider`, `--full-auto`, `--dangerously-bypass-approvals-and-sandbox`, `--output-last-message`, `--color`)
16+
- Generic `-c key=value` config overrides, exec review wrapper, and resume --last support
17+
- Grant-root approval handling for file changes and `Codex.AppServer.command_write_stdin/4`
18+
19+
### Changed
20+
21+
- Reasoning items now preserve `summary`/`content` structure instead of flattened text
22+
- App-server `turn.error` payloads are surfaced on `Codex.Events.TurnCompleted`
23+
24+
### Fixed
25+
26+
- Streamed turn failures now handle non-text `final_response` payloads without crashing and include `turn.error` details when present
27+
- Structured `/new` input blocks now reset conversation state for app-server/exec turn runs and streams
28+
- Tool guardrail and approval hook exceptions are surfaced as errors instead of crashing the turn
29+
- Progress telemetry metadata now merges even when base metadata is nil
30+
31+
### Documentation
32+
33+
- Updated README and API reference for new input types, exec flags, and app-server deltas
34+
835
## [0.4.3] - 2025-12-27
936

1037
### Added

README.md

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ An idiomatic Elixir SDK for embedding OpenAI's Codex agent in your workflows and
1616
## Features
1717

1818
- **End-to-End Codex Lifecycle**: Spawn, resume, and manage full Codex threads with rich turn instrumentation.
19-
- **Multi-Transport Support**: Default exec JSONL (`codex exec --experimental-json`) plus stateful app-server JSON-RPC over stdio (`codex app-server`).
20-
- **Upstream Compatibility**: Automatically handles select app-server protocol differences across Codex CLI versions (e.g. MCP list method rename fallbacks).
21-
- **Streaming & Structured Output**: Real-time events plus first-class JSON schema handling for deterministic parsing.
19+
- **Multi-Transport Support**: Default exec JSONL (`codex exec --experimental-json`) plus stateful app-server JSON-RPC over stdio (`codex app-server`) with multi-modal `UserInput` blocks.
20+
- **Upstream Compatibility**: Mirrors Codex CLI flags (profile/OSS/full-auto/color, config overrides, review/resume) and handles app-server protocol drift (e.g. MCP list method rename fallbacks).
21+
- **Streaming & Structured Output**: Real-time events plus reasoning summary/content preservation and typed app-server deltas.
2222
- **File & Attachment Pipeline**: Secure temp file registry, change events, and fixture harvesting helpers.
2323
- **Approval Hooks & Sandbox Policies**: Dynamic or static approval flows with registry-backed persistence.
2424
- **Tooling & MCP Integration**: Built-in registry for Codex tool manifests and MCP client helpers.
@@ -33,7 +33,7 @@ Add `codex_sdk` to your list of dependencies in `mix.exs`:
3333
```elixir
3434
def deps do
3535
[
36-
{:codex_sdk, "~> 0.4.3"}
36+
{:codex_sdk, "~> 0.4.4"}
3737
]
3838
end
3939
```
@@ -120,11 +120,25 @@ The SDK defaults to exec JSONL for backwards compatibility. To use the stateful
120120
{:ok, %{"data" => skills}} = Codex.AppServer.skills_list(conn, cwds: ["/project"])
121121
```
122122

123+
Multi-modal input is supported on app-server transport:
124+
125+
```elixir
126+
input = [
127+
%{type: :text, text: "Explain this screenshot"},
128+
%{type: :local_image, path: "/tmp/screenshot.png"}
129+
]
130+
131+
{:ok, result} = Codex.Thread.run(thread, input)
132+
```
133+
134+
Note: exec JSONL transport still accepts text input only; list inputs return `{:error, {:unsupported_input, :exec}}`.
135+
123136
App-server-only APIs include:
124137

125138
- `Codex.AppServer.thread_list/2`, `thread_archive/2`
126139
- `Codex.AppServer.model_list/2`, `config_read/2`, `config_write/4`, `config_batch_write/3`
127140
- `Codex.AppServer.turn_interrupt/3`
141+
- `Codex.AppServer.command_write_stdin/4` (interactive command stdin)
128142
- `Codex.AppServer.Account.*` and `Codex.AppServer.Mcp.*` endpoints
129143
- Approvals via `Codex.AppServer.subscribe/2` + `Codex.AppServer.respond/3`
130144

@@ -258,6 +272,13 @@ thread_id = "thread_abc123"
258272
{:ok, result} = Codex.Thread.run(thread, "Continue from where we left off")
259273
```
260274

275+
Resume the most recent session (equivalent to `codex exec resume --last`):
276+
277+
```elixir
278+
{:ok, thread} = Codex.resume_thread(:last)
279+
{:ok, result} = Codex.Thread.run(thread, "Continue from where we left off")
280+
```
281+
261282
### Configuration Options
262283

263284
```elixir
@@ -355,6 +376,9 @@ Codex respects upstream safe-command markers: tool events flagged with `requires
355376
bypass approval gating automatically, keeping low-risk workspace actions fast while still blocking
356377
requests that require review.
357378

379+
For app-server file-change approvals, hooks can return `{:allow, grant_root: "/path"}` to accept
380+
the proposed root for the current session.
381+
358382
Tool-call events can also arrive pre-approved via `approved_by_policy` (or `approved`) from the
359383
CLI; the SDK mirrors that bypass and skips hooks while still emitting telemetry. Sandbox warnings
360384
are normalized so Windows paths dedupe cleanly (e.g., `C:/Temp` and `C:\\Temp` coalesce). See
@@ -558,7 +582,14 @@ HexDocs hosts the complete documentation set referenced in `mix.exs`:
558582

559583
## Project Status
560584

561-
**Current Version**: 0.4.3 (Upstream sync: error details + config layering)
585+
**Current Version**: 0.4.4 (Upstream parity: app-server inputs + exec flags)
586+
587+
### v0.4.4 Highlights
588+
589+
- App-server `UserInput` lists (text/image/localImage), full thread/turn params, and sandbox policies
590+
- Typed app-server notifications for terminal interaction, reasoning summaries, and output deltas
591+
- Exec parity: profile/OSS/full-auto/color/output-last-message flags, generic `-c` overrides, review wrapper, resume --last
592+
- Reasoning items now preserve `summary`/`content` structure instead of flattened text
562593

563594
### v0.4.3 Highlights
564595

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.4.3
1+
0.4.4

docs/02-architecture.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,15 @@ defstruct [
120120

121121
**Key Functions**:
122122
```elixir
123-
@spec run(t(), String.t(), Codex.Turn.Options.t()) ::
123+
@spec run(t(), String.t() | [map()], Codex.Turn.Options.t()) ::
124124
{:ok, Codex.Turn.Result.t()} | {:error, term()}
125125

126-
@spec run_streamed(t(), String.t(), Codex.Turn.Options.t()) ::
126+
@spec run_streamed(t(), String.t() | [map()], Codex.Turn.Options.t()) ::
127127
{:ok, Enumerable.t()} | {:error, term()}
128128
```
129129

130+
App-server transport accepts `UserInput` block lists (text/image/localImage); exec JSONL expects text input.
131+
130132
**Execution Flow** (Blocking Mode):
131133
1. Create output schema file if needed
132134
2. Start `Codex.Exec` GenServer with options

0 commit comments

Comments
 (0)