Skip to content

Commit 0649d09

Browse files
committed
feat: 同步 feature/3.0.x——app-server WS 路线 + CLI 命令面对齐(Jackson 2 / JDK 17 适配)
- 自 3.0.x@2c15db6 同步 src/ 与双语 README(不含 pom.xml) - app-server WebSocket 路线整体引入;close 改为关自持 ExecutorService (HttpClient.close() 为 JDK 21 API,JDK 17 不可用),HttpClient 显式 绑定该 executor - Jackson 3→2 适配:tools.jackson.databind/core → com.fasterxml 同名包; 测试助手 readTree 包裹 checked JsonProcessingException - CLI 路线同步命令面对齐:queue/delete/agents/migrate-rollouts、login 四 认证形态(executeWithStdin)、exec 新旗标、sandbox --permission-profile 拼写修复、mcpServer 废弃 - pom.xml 保持本分支既有基线(JDK 17 + jackson-bom 2.22.1 + junit-jupiter 6.1.0),未改动 - 测试 222 个全绿(JDK 17 + Maven 3.9.16)
1 parent 7f279a2 commit 0649d09

24 files changed

Lines changed: 2441 additions & 83 deletions

README.md

Lines changed: 105 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
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

@@ -24,10 +26,14 @@
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

3238
The 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

4252
What 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

4758
Typical 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
81106
Version 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

109137
Single-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

115143
Key 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

138167
Gradle:
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

Comments
 (0)