feat(openai): support ChatGPT OAuth for Responses vision - #40
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 30, 2026, 4:14 PM ET / 20:14 UTC. ClawSweeper reviewWhat this changesThis PR distinguishes ChatGPT OAuth credentials from OpenAI Platform API keys, routes OAuth-backed Responses vision requests through the ChatGPT Codex backend, and adds refresh, credential-isolation, image, streaming, and concurrency coverage. Merge readinessThis PR has strong concrete proof and no discrete correctness defect found in the supplied branch review, but it introduces a new supported credential-routing contract to the ChatGPT Codex backend. Keep it open for an explicit maintainer decision on whether that backend and token-refresh behavior belong in Tachikoma’s public OpenAI provider surface. Priority: P2 Review scores
Verification
How this fits togetherTachikoma’s OpenAI Responses provider turns application model messages into streamed OpenAI requests. This change inserts credential classification and refresh handling before transport selection, preserving the Platform API route for API keys while sending qualifying ChatGPT OAuth sessions to the Codex Responses backend. flowchart LR
A[Application model message] --> B[OpenAI Responses provider]
B --> C[Resolve API key or ChatGPT OAuth]
C --> D{Credential type}
D -->|Platform API key| E[OpenAI Responses API]
D -->|ChatGPT OAuth| F[Refresh and account lookup]
F --> G[ChatGPT Codex Responses API]
E --> H[Streamed provider response]
G --> H
Decision needed
Why: The implementation is coherent and evidenced, but deciding to support a separate ChatGPT backend, account header, and refresh lifecycle is an SDK product and compatibility commitment rather than a mechanical patch choice. Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: If maintainers endorse ChatGPT OAuth as a supported Tachikoma capability, merge it as the single documented transport boundary, preserve API-key precedence and environment credential isolation, and coordinate the downstream Peekaboo submodule update after the source change lands. Do we have a high-confidence way to reproduce the issue? Yes for the reported OAuth mismatch, with medium confidence: the PR supplies a concrete live request/result and a committed integration-test path, but this read-only review could not execute the credential-bound test against a real account. Is this the best way to solve the issue? Unclear: the implementation is a focused solution with strong compatibility coverage, but whether the ChatGPT Codex backend is the best supported Tachikoma transport is a maintainer product-contract decision. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 590cbc5a6ebf. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (12 earlier review cycles; latest 8 shown)
|
What problem this solves
ChatGPT OAuth access tokens are not OpenAI Platform API keys. Tachikoma previously resolved the stored OAuth access token as a generic bearer credential and sent it to
https://api.openai.com/v1/responses. That endpoint rejects the token before image understanding can run.The OAuth path must instead use the ChatGPT Codex Responses backend, include the ChatGPT account identifier carried by the token, and safely refresh rotated OAuth credentials. Stored login credentials persist their refresh chain; credentials explicitly supplied through the environment remain process-local. The public OpenAI API-key path remains unchanged.
Request path
Implementation
max_output_tokensfield from Codex requestsEvidence
Red: the previous endpoint rejects the OAuth credential
A minimal Responses request was sent with the same valid ChatGPT OAuth access token used by the green test below. The token is redacted here.
Observed response:
This is the concrete failure behind the bug: login succeeds, but the resulting OAuth token cannot be used as a Platform API credential.
Green: live OAuth vision through the Codex backend
The committed live integration test uses a deterministic 16x16 solid-red PNG and the prompt:
Sanitized request observed from the provider:
{ "model": "gpt-5.6-sol", "stream": true, "store": false, "input": [{ "role": "user", "content": [ {"type": "input_text", "text": "Reply with the single lowercase word red if this image is red."}, {"type": "input_image", "image_url": "data:image/png;base64,<redacted>"} ] }] }The request was sent to:
Observed SSE result:
Result: the real GPT-5.6 Sol OAuth vision request passed in 6.252 seconds.
The local machine cannot reach
chatgpt.comdirectly, so this live invocation supplied a SOCKS-backedURLSessiononly to the test instance. No proxy implementation is included in this PR.Reproducibility
On a machine that can reach the Codex endpoint directly and has Peekaboo-compatible OpenAI OAuth credentials:
The input image is embedded in the test, so the visual assertion is deterministic and does not capture the host desktop.
Credential-boundary, refresh, and concurrency proof
The focused authentication suite directly verifies both persistence modes and their failure/concurrency boundaries:
The environment tests assert that
TKCredentialStore().load()remains empty, that a pre-existing stored account remains byte-for-byte unchanged, that rotated refresh tokens continue in memory, and that changes to the environment source or ignore setting discard the cache. The stored-session test verifies atomic persistence. Failure tests verify HTTP and malformed responses preserve existing credentials, while the concurrency test starts eight simultaneous callers and observes one refresh request with eight identical results.Reproduction command:
/usr/bin/arch -arm64 swift test --filter AuthManagerTestsObserved result: 19 tests passed.
Compatibility and upgrade matrix
api.openai.com/v1/responses; do not enter Codex OAuth transportResponses provider hits /v1/responses and encodes bodyOpenAI API key credential is preferred over OAuth token noise;OAuth tokens are not loaded as OpenAI API keysenv preferred over credsOpenAI Codex OAuth prefers a valid environment accountCodex OAuth provider sends image input through ChatGPT Responses transportfor GPT-5.5 and all GPT-5.6 variantsauth.openai.com, rotate tokens, and persist access/refresh/expiry togetherOpenAI Codex OAuth refresh rotates and persists credentialsOpenAI Codex OAuth caches refreshed environment credentials without persistingOpenAI Codex OAuth continues an environment refresh chain in memoryOpenAI Codex OAuth refreshes an explicit environment account over another stored accountOpenAI Codex OAuth refresh ignores an unrefreshable environment tokenOpenAI Codex OAuth concurrent callers share one refreshverifies eight callers and one refresh requestEvery compatibility and upgrade path in this matrix is covered by a focused direct test.
User impact
Applications embedding Tachikoma, including Peekaboo, can use OpenAI OAuth credentials for Responses-based visual understanding without requiring a separate OpenAI API key. Existing API-key configurations retain their current endpoint and request behavior. Environment-provided sessions remain ephemeral; use the normal login flow when refresh rotation must persist across launches.
Downstream dependency
This PR is a prerequisite for openclaw/Peekaboo#293, which updates Peekaboo's OAuth availability handling and Tachikoma submodule pointer. Peekaboo #293 is ready for review but must merge after this PR.
Validation
redin 6.252 seconds/usr/bin/arch -arm64 swift test --filter AuthManagerTests— 19 tests passed/usr/bin/arch -arm64 swift test --filter OpenAIResponsesProviderTests— 30 tests passed, including GPT-5.5 and all GPT-5.6 variants/usr/bin/arch -arm64 swift test --no-parallel— 842 of 843 tests passed; the only failure is an unrelated existing OpenAI audio network-error test that sends to the realapi.openai.comendpoint and timed out after 60 secondsgit diff --check