feat: add Codex subscription ChatModel - #25
Open
tuannx wants to merge 1 commit into
Open
Conversation
tuannx
marked this pull request as ready for review
July 24, 2026 16:25
tuannx
force-pushed
the
codex/codex-subscription
branch
from
July 27, 2026 05:34
f175680 to
0f887e9
Compare
Add embabel-agent-codex, an experimental module exposing a Spring AI ChatModel backed by a Codex-enabled ChatGPT subscription: OAuth device login, module-owned credential storage and refresh, the Codex Responses transport, and Spring AI request/response mapping. The module never spawns the Codex CLI and never uses an OpenAI API key. Codex CLI credentials may be imported once as an explicit bootstrap; that import reads ~/.codex/auth.json and never writes to it. Scope is the reusable core only. Auto-configuration, a starter, a fixed model catalog, and reactive token streaming are intentionally excluded. Targets the 2.0.0 platform (Spring Boot 4.1, Spring AI 2.0): - Retry uses org.springframework.core.retry, as Spring Boot 4 no longer manages org.springframework.retry:spring-retry. Because the core RetryTemplate wraps the final failure in a RetryException rather than rethrowing it, CodexChatModel unwraps it so callers keep seeing this module's typed exceptions. - CodexChatOptions implements mutate() in place of the removed copy(). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Avh94V6HqddWvg131jzLAn Signed-off-by: TuanNX <tuannx87@gmail.com>
tuannx
force-pushed
the
codex/codex-subscription
branch
from
July 27, 2026 06:15
0f887e9 to
68bfea5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Scope
This is the reusable core only. It intentionally excludes auto-configuration, a starter, a fixed model catalog, and reactive token streaming. The README calls out refresh-token ownership, subscription versus API billing, and the private endpoint stability boundary.
Platform migration
Two upstream removals in the 2.0.0 platform affect this module:
org.springframework.retry:spring-retry, so retry usesorg.springframework.core.retryfrom Spring Framework 7. The coreRetryTemplatewraps the final failure in aRetryExceptionrather than rethrowing it, soCodexChatModelunwraps it and callers keep seeing this module's typed exceptions.ChatOptions.copy()was replaced bymutate(), whichCodexChatOptionsnow implements.Prior art
Validation
mvn -B verifygreen, 11/11 modulesgpt-5.6-sol: auth, POST to the Responses endpoint, SSE aggregation, and ChatResponse mapping all succeededCodexAuthExceptioncarrying the upstreamrefresh_token_reusedmessage, not a wrapped retry exceptionDependency resolution for the local runs was served from an already-populated local repository; CI remains the authority on a cold resolve.
Upstream mapping
No matching upstream Codex, OpenAI, or subscription issue/PR was found. Draft PR #22 only overlaps the Experimental Modules README table and is otherwise unrelated.