22
33[ English] ( ./README.md ) | [ 简体中文] ( ./README.zh-CN.md )
44
5- [ ![ Java] ( https://img.shields.io/badge/Java-17 -orange )] ( https://github.com/easy-4-java/codex-java-sdk ) [ ![ License] ( https://img.shields.io/badge/license-Apache%202.0-green )] ( https://www.apache.org/licenses/LICENSE-2.0.txt )
5+ [ ![ Java] ( https://img.shields.io/badge/Java-21 -orange )] ( https://github.com/easy-4-java/codex-java-sdk ) [ ![ License] ( https://img.shields.io/badge/license-Apache%202.0-green )] ( https://www.apache.org/licenses/LICENSE-2.0.txt )
66
7- > Java SDK for the [ Codex CLI] ( https://github.com/openai/codex ) : subprocess
8- > integration that drives the local ` codex ` agent (exec, interactive sessions,
9- > session resume / fork / archive, doctor, review) from Java.
7+ > Java SDK for the [ Codex CLI] ( https://github.com/openai/codex ) with two
8+ > integration routes: a subprocess wrapper that drives the local ` codex `
9+ > agent (exec, interactive sessions, session resume / fork / archive, doctor,
10+ > review), and a JSON-RPC 2.0 over WebSocket client for a remote Codex
11+ > app-server (` thread/start ` → ` turn/start ` → notification stream).
1012
1113## Table of Contents
1214
2426
2527## 1. Project Overview
2628
27- ` codex-java-sdk ` lets Java applications run the
28- [ Codex CLI] ( https://github.com/openai/codex ) agent (` codex ` ) as a local subprocess.
29- It is a ** CLI wrapper** , not a direct OpenAI API client — every call maps to a real
30- ` codex ` command line invocation.
29+ ` codex-java-sdk ` lets Java applications integrate the
30+ [ Codex CLI] ( https://github.com/openai/codex ) agent (` codex ` ) through two
31+ routes. Neither route is a direct OpenAI API client.
32+
33+ - ** CLI route (local subprocess)** — every call maps to a real ` codex `
34+ command line invocation.
35+ - ** App-server route (remote long connection)** — a JSON-RPC 2.0 over
36+ WebSocket client for a running Codex app-server.
3137
3238The SDK covers:
3339
@@ -38,11 +44,16 @@ The SDK covers:
3844- ** Parsed models** — ` CodexEvent ` (JSONL events), ` CodexSession ` , ` CodexDoctorReport ` .
3945- ** Utilities** — ` doctor ` , ` review ` , ` login ` / ` logout ` , MCP management, ` update ` ,
4046 ` features ` , shell ` completion ` .
47+ - ** App-server WebSocket route** — ` CodexAppServerClient ` with per-turn
48+ connections, ` thread/start ` / ` thread/resume ` reuse via a bounded
49+ ` sessionKey → threadId ` LRU, streaming agent-message deltas and
50+ ` turn/completed ` finalization.
4151
4252What it is ** not** :
4353
4454- Not an OpenAI API client (no direct HTTP calls to the OpenAI API).
45- - Not a replacement for the ` codex ` binary — the CLI must be installed and runnable.
55+ - Not a replacement for the ` codex ` binary — the CLI must be installed and runnable
56+ (local route), or a Codex app-server must be reachable (WebSocket route).
4657
4758Typical scenarios:
4859
@@ -53,6 +64,7 @@ Typical scenarios:
5364| Long-running interactive agent | ` startSession(prompt) ` / ` resumeSession(sessionId) ` |
5465| Reproduce a session in a sandbox | ` forkSession(sessionId) ` / ` execResume(sessionId, prompt) ` |
5566| Environment diagnostics | ` doctorSummary() ` / ` doctorJson() ` |
67+ | Remote agent with session continuity | ` CodexAppServerClient.runTurn(request) ` with ` sessionKey ` |
5668
5769## 2. Features & Status
5870
@@ -64,19 +76,32 @@ Typical scenarios:
6476| Interactive sessions | Active development | ` startSession() ` , ` startSession(prompt) ` , ` startSession(GlobalOptions, prompt) ` |
6577| Session lifecycle | Active development | ` resumeSession ` , ` resumeLastSession ` , ` forkSession ` , ` forkLastSession ` , ` archiveSession ` , ` unarchiveSession ` , ` execResume ` |
6678| Doctor & review | Active development | ` doctor ` , ` doctorJson ` , ` doctorSummary ` , ` review ` , ` reviewCommit ` , ` reviewBase ` |
67- | Auth / MCP / misc | Active development | ` login ` , ` logout ` , ` mcpList ` / ` mcpAdd ` / ` mcpGet ` / ` mcpRemove ` , ` update ` , ` features ` , ` completion ` , ` app ` |
68- | Config model | Active development | ` CodexClientConfig ` POJO (plain, Spring-bindable) |
79+ | Auth / MCP / misc | Active development | ` login ` , ` loginWithApiKey ` , ` loginWithAccessToken ` , ` loginDeviceAuth ` , ` loginStatus ` , ` logout ` , ` mcpList ` / ` mcpAdd ` / ` mcpGet ` / ` mcpRemove ` / ` mcpLogin ` / ` mcpLogout ` , ` update ` , ` features ` , ` completion ` , ` app ` |
80+ | Session admin | Active development | ` archiveSession ` , ` unarchiveSession ` , ` queue ` , ` deleteSession ` , ` deleteSessionForce ` , ` agents ` , ` migrateRollouts ` |
81+ | App-server WebSocket route | Active development | ` CodexAppServerClient.runTurn ` / ` runTurnAsync ` , ` thread/start ` / ` thread/resume ` , agent-message deltas, ` sessionKey → threadId ` LRU (1000) |
82+ | Config model | Active development | ` CodexClientConfig ` POJO (plain, Spring-bindable), ` CodexAppServerConfig ` POJO |
83+
84+ > ** Note** : ` codex mcp-server ` was removed upstream — ` CodexClient.mcpServer() `
85+ > is deprecated in favour of ` appServer(...) ` . ` ExecOptions ` additionally
86+ > supports ` --ignore-rules ` / ` --ignore-user-config ` , and ` GlobalOptions `
87+ > supports ` --remote ` / ` --remote-auth-token-env ` for daemon-backed TUI runs.
6988
70- > ** Assumption** : the capability statuses above reflect the current state of the
71- > 1.0.x branch; the module is under active development.
89+ > ** Assumption** : the capability statuses above reflect the current state of
90+ > the active branch; the module is under active development.
7291
7392## 3. Requirements & Compatibility
7493
7594| Requirement | Version / Notes |
7695| :--- | :--- |
77- | JDK | 17 + |
96+ | JDK | 21 + |
7897| Maven | 3.0+ (enforced; Maven Wrapper ` ./mvnw ` included) |
79- | Codex CLI | ` codex ` must be installed and available (` localExecutable ` configures the path) |
98+ | Codex CLI | Local route: ` codex ` must be installed and available (` localExecutable ` configures the path) |
99+ | Codex app-server | WebSocket route only: a reachable app-server (` baseUrl ` accepts ws/wss/http/https) |
100+
101+ > ** Note** : the app-server WebSocket route uses the JDK built-in
102+ > ` java.net.http.HttpClient ` (JDK 11+). It is available on the ` feature/2.0.x `
103+ > and ` feature/3.0.x ` lines; the ` feature/1.0.x ` (JDK 8) line ships the CLI
104+ > route only.
80105
81106Version lines:
82107
@@ -89,35 +114,39 @@ Version lines:
89114## 4. Architecture & Modules
90115
91116``` text
92- +------------------+ +------------------------------------------+
93- | Java application | | codex-java-sdk |
94- | |-->| CodexClient (facade) |
95- | prompt / options | | | CodexCli (command mapping) |
96- | | | | | CodexCliExecutor |
97- | | | | | `codex` child process |
98- | | | | CodexCliResult |
99- +------------------+ | | CodexEvent/CodexSession/DoctorReport|
100- +-------------------+----------------------+
117+ +------------------+ +---------------------------------------------+
118+ | Java application | | codex-java-sdk |
119+ | |-->| Route 1 (local): CodexClient (facade) |
120+ | prompt / options | | | CodexCli (command mapping) |
121+ | | | | | CodexCliExecutor |
122+ | | | | | `codex` child process |
123+ | | | | CodexCliResult |
124+ | | | Route 2 (remote): CodexAppServerClient |
125+ | | | | JSON-RPC 2.0 over WebSocket |
126+ | | | | thread/start -> turn/start -> events |
127+ | | | CodexEvent/CodexSession/CodexDoctorReport |
128+ +------------------+ +-------------------+-------------------------+
101129 |
102130 v
103131 +-------------------------------------------+
104- | Local `codex` CLI (exec, session, doctor, |
105- | review, login, ...) |
132+ | Local `codex` CLI (route 1) or remote |
133+ | Codex app-server (route 2) |
106134 +-------------------------------------------+
107135```
108136
109137Single-module Maven project (` packaging: jar ` ). No child modules.
110138
111139| Artifact | Responsibility |
112140| :--- | :--- |
113- | ` io.github.easy4j:codex-java-sdk ` | CLI facade, command mapping, subprocess executor, result & parsed models |
141+ | ` io.github.easy4j:codex-java-sdk ` | CLI facade, command mapping, subprocess executor, WebSocket app-server client, results & parsed models |
114142
115143Key packages:
116144
117- | Package | Content |
145+ | Package | Contents |
118146| :--- | :--- |
119147| ` io.github.easy4j.codex ` | ` CodexClient ` , ` CodexClientConfig ` |
120148| ` io.github.easy4j.codex.cli ` | ` CodexCli ` , ` CodexCliExecutor ` , ` CodexCliResult ` |
149+ | ` io.github.easy4j.codex.appserver ` | ` CodexAppServerClient ` , ` CodexAppServerConfig ` , ` AppServerTurnRequest ` , ` AppServerTurnResult ` , ` ThreadMappingCache ` , ` CodexAppServerException ` |
121150| ` io.github.easy4j.codex.model ` | ` CodexEvent ` , ` CodexSession ` , ` CodexDoctorReport ` |
122151
123152## 5. Installation
@@ -131,14 +160,14 @@ Maven:
131160<dependency >
132161 <groupId >io.github.easy4j</groupId >
133162 <artifactId >codex-java-sdk</artifactId >
134- <version >2 .0.x.x.20260630-SNAPSHOT</version >
163+ <version >3 .0.x.x.20260630-SNAPSHOT</version >
135164</dependency >
136165```
137166
138167Gradle:
139168
140169``` groovy
141- implementation 'io.github.easy4j:codex-java-sdk:2 .0.x.x.20260630-SNAPSHOT'
170+ implementation 'io.github.easy4j:codex-java-sdk:3 .0.x.x.20260630-SNAPSHOT'
142171```
143172
144173## 6. Quick Start
@@ -197,6 +226,19 @@ There is no configuration file of its own. Key fields:
197226| ` strictConfig ` | boolean | ` false ` | Fail on unknown config fields |
198227| ` enable ` / ` disable ` | String[ ] | - | Features to enable / disable |
199228
229+ ### 7.1 ` CodexAppServerConfig ` (app-server WebSocket route)
230+
231+ Plain POJO (Spring ` @ConfigurationProperties ` -bindable). Field names mirror the
232+ commonly used ` CodexEndpoint ` binding:
233+
234+ | Field | Type | Default | Description |
235+ | :--- | :--- | :--- | :--- |
236+ | ` baseUrl ` | String | - | App-server base URL (` ws:// ` /` wss:// ` as-is, ` http:// ` /` https:// ` upgraded) |
237+ | ` token ` | String | - | Bearer token sent as ` Authorization: Bearer <token> ` on the handshake |
238+ | ` connectTimeoutMillis ` | int | ` 5000 ` | TCP/TLS + WebSocket handshake timeout |
239+ | ` readTimeoutMillis ` | int | ` 120000 ` | Upper bound for a whole turn (connect → ` turn/completed ` ) |
240+ | ` maxSessionMappings ` | int | ` 1000 ` | Bound of the ` sessionKey → threadId ` LRU; evicted sessions start fresh threads |
241+
200242## 8. Core Usage / API
201243
202244### 8.1 JSONL events
@@ -222,6 +264,36 @@ try (CodexClient client = new CodexClient(config)) {
222264}
223265```
224266
267+ ### 8.3 App-server WebSocket route (remote Codex)
268+
269+ ``` java
270+ import io.github.easy4j.codex.appserver.AppServerTurnRequest ;
271+ import io.github.easy4j.codex.appserver.AppServerTurnResult ;
272+ import io.github.easy4j.codex.appserver.CodexAppServerClient ;
273+ import io.github.easy4j.codex.appserver.CodexAppServerConfig ;
274+
275+ CodexAppServerConfig config = new CodexAppServerConfig ();
276+ config. setBaseUrl(" ws://codex-host:8081" ); // http(s) is upgraded to ws(s) automatically
277+ config. setToken(" capability-token" );
278+ config. setReadTimeoutMillis(120_000 );
279+
280+ try (CodexAppServerClient client = new CodexAppServerClient (config)) {
281+ AppServerTurnResult result = client. runTurn(AppServerTurnRequest . builder()
282+ .prompt(" Fix the failing test" )
283+ .sessionKey(" chat-42" ) // enables thread/resume reuse
284+ .onDelta(delta - > System . out. print(delta)) // agentMessage deltas, in order
285+ .build());
286+ System . out. println(result. getThreadId() + " -> " + result. getContent());
287+ }
288+ ```
289+
290+ The turn maps to ` thread/start ` (or ` thread/resume ` when ` sessionKey ` already
291+ maps to a thread id) → ` turn/start ` → ` item/completed ` (only agent messages
292+ surface) → ` turn/completed ` . Unknown notifications are logged at debug level
293+ and never interrupt the turn. Failures — connection, JSON-RPC error,
294+ ` turn/failed ` , ` error ` , premature close or read timeout — surface as
295+ ` CodexAppServerException ` .
296+
225297## 9. Testing & Build
226298
227299``` bash
@@ -230,9 +302,9 @@ try (CodexClient client = new CodexClient(config)) {
230302
231303- The build is configured with the JaCoCo Maven plugin (report + ` check ` goal with a
232304 90% line-coverage rule bound to the ` verify ` phase; ` haltOnFailure=false ` ).
233- - ** Assumption ** : the 1.0.x branch currently checks in no test sources under
234- ` src/test ` ; coverage thresholds are therefore enforced only when tests exist .
235- - No CI workflow files are present under ` .github/ ` in this worktree .
305+ - The active branch ships a full test suite (206 tests on ` feature/3.0.x ` ), including
306+ end-to-end WebSocket contract tests against an in-process fake app-server .
307+ - CI workflow: ` .github/workflows/ci.yml ` .
236308
237309## 10. Versioning & Branches
238310
0 commit comments