44
55[ ![ 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
@@ -65,18 +77,20 @@ Typical scenarios:
6577| Session lifecycle | Active development | ` resumeSession ` , ` resumeLastSession ` , ` forkSession ` , ` forkLastSession ` , ` archiveSession ` , ` unarchiveSession ` , ` execResume ` |
6678| Doctor & review | Active development | ` doctor ` , ` doctorJson ` , ` doctorSummary ` , ` review ` , ` reviewCommit ` , ` reviewBase ` |
6779| 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) |
80+ | App-server WebSocket route | Active development | ` CodexAppServerClient.runTurn ` / ` runTurnAsync ` , ` thread/start ` / ` thread/resume ` , agent-message deltas, ` sessionKey → threadId ` LRU (1000) |
81+ | Config model | Active development | ` CodexClientConfig ` POJO (plain, Spring-bindable), ` CodexAppServerConfig ` POJO |
6982
70- > ** Assumption** : the capability statuses above reflect the current state of the
71- > 1.0.x branch; the module is under active development.
83+ > ** Assumption** : the capability statuses above reflect the current state of
84+ > the active branch; the module is under active development.
7285
7386## 3. Requirements & Compatibility
7487
7588| Requirement | Version / Notes |
7689| :--- | :--- |
7790| JDK | 21+ |
7891| Maven | 3.0+ (enforced; Maven Wrapper ` ./mvnw ` included) |
79- | Codex CLI | ` codex ` must be installed and available (` localExecutable ` configures the path) |
92+ | Codex CLI | Local route: ` codex ` must be installed and available (` localExecutable ` configures the path) |
93+ | Codex app-server | WebSocket route only: a reachable app-server (` baseUrl ` accepts ws/wss/http/https) |
8094
8195Version lines:
8296
@@ -89,35 +103,39 @@ Version lines:
89103## 4. Architecture & Modules
90104
91105``` 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- +-------------------+----------------------+
106+ +------------------+ +---------------------------------------------+
107+ | Java application | | codex-java-sdk |
108+ | |-->| Route 1 (local): CodexClient (facade) |
109+ | prompt / options | | | CodexCli (command mapping) |
110+ | | | | | CodexCliExecutor |
111+ | | | | | `codex` child process |
112+ | | | | CodexCliResult |
113+ | | | Route 2 (remote): CodexAppServerClient |
114+ | | | | JSON-RPC 2.0 over WebSocket |
115+ | | | | thread/start -> turn/start -> events |
116+ | | | CodexEvent/CodexSession/CodexDoctorReport |
117+ +------------------+ +-------------------+-------------------------+
101118 |
102119 v
103120 +-------------------------------------------+
104- | Local `codex` CLI (exec, session, doctor, |
105- | review, login, ...) |
121+ | Local `codex` CLI (route 1) or remote |
122+ | Codex app-server (route 2) |
106123 +-------------------------------------------+
107124```
108125
109126Single-module Maven project (` packaging: jar ` ). No child modules.
110127
111128| Artifact | Responsibility |
112129| :--- | :--- |
113- | ` io.github.easy4j:codex-java-sdk ` | CLI facade, command mapping, subprocess executor, result & parsed models |
130+ | ` io.github.easy4j:codex-java-sdk ` | CLI facade, command mapping, subprocess executor, WebSocket app-server client, results & parsed models |
114131
115132Key packages:
116133
117- | Package | Content |
134+ | Package | Contents |
118135| :--- | :--- |
119136| ` io.github.easy4j.codex ` | ` CodexClient ` , ` CodexClientConfig ` |
120137| ` io.github.easy4j.codex.cli ` | ` CodexCli ` , ` CodexCliExecutor ` , ` CodexCliResult ` |
138+ | ` io.github.easy4j.codex.appserver ` | ` CodexAppServerClient ` , ` CodexAppServerConfig ` , ` AppServerTurnRequest ` , ` AppServerTurnResult ` , ` ThreadMappingCache ` , ` CodexAppServerException ` |
121139| ` io.github.easy4j.codex.model ` | ` CodexEvent ` , ` CodexSession ` , ` CodexDoctorReport ` |
122140
123141## 5. Installation
@@ -197,6 +215,19 @@ There is no configuration file of its own. Key fields:
197215| ` strictConfig ` | boolean | ` false ` | Fail on unknown config fields |
198216| ` enable ` / ` disable ` | String[ ] | - | Features to enable / disable |
199217
218+ ### 7.1 ` CodexAppServerConfig ` (app-server WebSocket route)
219+
220+ Plain POJO (Spring ` @ConfigurationProperties ` -bindable). Field names mirror the
221+ commonly used ` CodexEndpoint ` binding:
222+
223+ | Field | Type | Default | Description |
224+ | :--- | :--- | :--- | :--- |
225+ | ` baseUrl ` | String | - | App-server base URL (` ws:// ` /` wss:// ` as-is, ` http:// ` /` https:// ` upgraded) |
226+ | ` token ` | String | - | Bearer token sent as ` Authorization: Bearer <token> ` on the handshake |
227+ | ` connectTimeoutMillis ` | int | ` 5000 ` | TCP/TLS + WebSocket handshake timeout |
228+ | ` readTimeoutMillis ` | int | ` 120000 ` | Upper bound for a whole turn (connect → ` turn/completed ` ) |
229+ | ` maxSessionMappings ` | int | ` 1000 ` | Bound of the ` sessionKey → threadId ` LRU; evicted sessions start fresh threads |
230+
200231## 8. Core Usage / API
201232
202233### 8.1 JSONL events
@@ -222,6 +253,36 @@ try (CodexClient client = new CodexClient(config)) {
222253}
223254```
224255
256+ ### 8.3 App-server WebSocket route (remote Codex)
257+
258+ ``` java
259+ import io.github.easy4j.codex.appserver.AppServerTurnRequest ;
260+ import io.github.easy4j.codex.appserver.AppServerTurnResult ;
261+ import io.github.easy4j.codex.appserver.CodexAppServerClient ;
262+ import io.github.easy4j.codex.appserver.CodexAppServerConfig ;
263+
264+ CodexAppServerConfig config = new CodexAppServerConfig ();
265+ config. setBaseUrl(" ws://codex-host:8081" ); // http(s) is upgraded to ws(s) automatically
266+ config. setToken(" capability-token" );
267+ config. setReadTimeoutMillis(120_000 );
268+
269+ try (CodexAppServerClient client = new CodexAppServerClient (config)) {
270+ AppServerTurnResult result = client. runTurn(AppServerTurnRequest . builder()
271+ .prompt(" Fix the failing test" )
272+ .sessionKey(" chat-42" ) // enables thread/resume reuse
273+ .onDelta(delta - > System . out. print(delta)) // agentMessage deltas, in order
274+ .build());
275+ System . out. println(result. getThreadId() + " -> " + result. getContent());
276+ }
277+ ```
278+
279+ The turn maps to ` thread/start ` (or ` thread/resume ` when ` sessionKey ` already
280+ maps to a thread id) → ` turn/start ` → ` item/completed ` (only agent messages
281+ surface) → ` turn/completed ` . Unknown notifications are logged at debug level
282+ and never interrupt the turn. Failures — connection, JSON-RPC error,
283+ ` turn/failed ` , ` error ` , premature close or read timeout — surface as
284+ ` CodexAppServerException ` .
285+
225286## 9. Testing & Build
226287
227288``` bash
@@ -230,9 +291,9 @@ try (CodexClient client = new CodexClient(config)) {
230291
231292- The build is configured with the JaCoCo Maven plugin (report + ` check ` goal with a
232293 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 .
294+ - The active branch ships a full test suite (206 tests on ` feature/3.0.x ` ), including
295+ end-to-end WebSocket contract tests against an in-process fake app-server .
296+ - CI workflow: ` .github/workflows/ci.yml ` .
236297
237298## 10. Versioning & Branches
238299
0 commit comments