Skip to content

Migrate OpenAI client to the official openai-java SDK#194

Merged
IRus merged 1 commit into
mainfrom
migrate-openai-java-sdk
Jun 9, 2026
Merged

Migrate OpenAI client to the official openai-java SDK#194
IRus merged 1 commit into
mainfrom
migrate-openai-java-sdk

Conversation

@IRus

@IRus IRus commented Jun 8, 2026

Copy link
Copy Markdown
Member

What

Replaces the hand-rolled Ktor + kotlinx.serialization OpenAI client (GptApi) with the official com.openai:openai-java SDK (4.39.1, already declared in the version catalog).

Why

Production logs showed UserNoteService note generation failing with a misleading error:

kotlinx.serialization.MissingFieldException: Fields [id, object, created, model,
choices, usage, system_fingerprint] are required for type ... ChatCompletionResponse,
but they were missing at path: $

GptApi.complete() called .body<ChatCompletionResponse>() unconditionally, with no status check. So any non-2xx response from OpenAI (its body is {"error": {...}}) was decoded against the success shape and surfaced as a generic "all fields missing" deserialization error — hiding the real API error (bad model, auth, quota, etc.).

The official SDK throws typed errors on failure, so the actual OpenAI error now reaches UserNoteService's catch and gets logged. It also removes the hand-maintained request/response models.

Changes

  • GptApi now wraps OpenAIClient and exposes a single complete(model, systemPrompt, userPrompt, temperature, maxTokens, …) returning the message content. Blocking SDK calls run on Dispatchers.IO.
  • GptApiModule builds the OpenAIOkHttpClient from the existing "gpt" config (apiKey + organization); no longer depends on HttpClientModule.
  • GptService and UserNoteService updated to the new signature.
  • Removed the unused getModels() and all hand-rolled ChatCompletionRequest/ChatCompletionResponse/OpenApiList/Model models.
  • Mirrors the existing pattern already used by the sibling tgpt module (OpenAiModule/OpenAiService).

Notes

  • Chat Completions semantics, model (gpt-5.4-mini), and all params (temperature/topP/penalties/maxTokens) are preserved.
  • The separate jOOQ GarbageMessages mapping NPE seen in the same logs was fixed independently on main (38f4367) and is not part of this PR.

Test

  • ./gradlew :tgkotbot:compileKotlin :tgkotbot:compileTestKotlin — green (KSP regenerates the DI builder for the new GptApiModule constructor).

🤖 Generated with Claude Code

Replace the hand-rolled Ktor + kotlinx.serialization OpenAI client with
the official com.openai:openai-java SDK (already declared in the version
catalog). The old GptApi.complete() called .body<ChatCompletionResponse>()
unconditionally, so any non-2xx from OpenAI was decoded against the success
shape and surfaced as a misleading kotlinx MissingFieldException, hiding the
real API error (bad model, auth, quota, etc.).

GptApi now wraps OpenAIClient and exposes a single complete(...) that returns
the message content; the OkHttp client is built in GptApiModule from the
existing "gpt" config (apiKey + organization). Blocking SDK calls run on
Dispatchers.IO. GptService and UserNoteService are updated to the new
signature; the unused getModels() and the hand-rolled request/response
models are removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@IRus IRus merged commit 15c8776 into main Jun 9, 2026
7 of 8 checks passed
@IRus IRus deleted the migrate-openai-java-sdk branch June 9, 2026 07:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant