Skip to content

~70% code duplication between OpenAiLlmClient and GeminiLlmClient #7

@rogue-socket

Description

@rogue-socket

Summary

184 lines are copy-pasted identically between OpenAiLlmClient.kt (319 lines) and GeminiLlmClient.kt (359 lines). Only ~77-98 lines per client are genuinely unique. Any change to shared logic must be manually applied in both files.

Duplicated methods (identical, copy-paste)

Method OpenAI lines Gemini lines
executeRequest() 90-110 95-115
buildSystemPrompt() 151-159 148-156
buildUserContent() 162-175 159-172
formatAction() 177-185 174-182
scaleBitmap() 197-207 193-203
parseActionSchema() 216-224 215-223
toDecision() 226-267 225-266
requireOnly() 269-282 268-281
buildActionSchema() 284-301 283-300
validateNoUnknownKeys() 307-312 302-307
logFailure() 303-305 309-311
Error-handling shell 71-87 76-92

Parts that genuinely differ

  1. URL construction and auth — Bearer header vs query param
  2. Request body structure (buildRequestJson()) — different JSON schemas
  3. Response parsing (parseAssistantContent()) — choices[0].message.content vs candidates[0].content.parts[].text
  4. Image encoding (encodeImage()) — data URL wrapper vs raw base64
  5. Data model classesOpenAiModels.kt vs inline Gemini classes

Drift already detected

LOG_TAG is "LlmClient" in OpenAI but "GeminiLlmClient" in Gemini — the OpenAI value was never updated.

Suggestion

Extract shared logic into an abstract base class or shared utility, leaving only the API-specific parts (request building, response parsing, auth) in the concrete implementations.

Files

  • action-executor/src/main/java/com/scroller/agent/executor/OpenAiLlmClient.kt
  • action-executor/src/main/java/com/scroller/agent/executor/GeminiLlmClient.kt

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions