feat(captain): CAPTAIN_CODEX_MODEL_OVERRIDE pra usar modelos fora do catalog do RubyLLM

Adiciona sobrescrita de modelo no proxy. Motivação: o RubyLLM valida o modelo
contra um catalog interno antes de enviar a call. Modelos novos (gpt-5.4,
gpt-5.3-codex) ainda não estão nesse catalog e geram RubyLLM::ModelNotFoundError.

Com CAPTAIN_CODEX_MODEL_OVERRIDE definida, o Translator substitui o modelo do
body antes de enviar ao Codex. Captain continua passando um modelo reconhecido
(gpt-5.2), mas o Codex recebe o modelo real (gpt-5.4).

Exemplo:
  InstallationConfig.find_or_initialize_by(name: "CAPTAIN_CODEX_MODEL_OVERRIDE")
    .update!(value: "gpt-5.4", locked: false)

Validado: curl → proxy → Codex retorna "model":"gpt-5.4" no response.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rodribm10 2026-04-22 17:55:22 -03:00
parent b457e84c2f
commit 9e8550dd45

View File

@ -4,6 +4,15 @@
#
# Opera em cima de hashes — sem I/O. I/O fica no Client.
class Captain::Codex::Translator
# Permite forçar um modelo diferente no proxy via CAPTAIN_CODEX_MODEL_OVERRIDE.
# Útil pra usar modelos que o RubyLLM ainda não reconhece no catalog
# (ex: gpt-5.4, gpt-5.3-codex) — o Captain continua mandando gpt-5.2
# (validado pelo RubyLLM) e o proxy substitui antes de chegar no Codex.
def self.override_model(requested)
override = InstallationConfig.find_by(name: 'CAPTAIN_CODEX_MODEL_OVERRIDE')&.value.presence
override || requested
end
# --- Request: chat completions → responses ---
# chat_body: hash no formato OpenAI Chat Completions.
@ -13,7 +22,7 @@ class Captain::Codex::Translator
instructions, input = split_system(messages)
body = {
model: chat_body['model'] || chat_body[:model],
model: override_model(chat_body['model'] || chat_body[:model]),
input: input,
# Codex exige o campo instructions sempre. Se não vier system message,
# usamos uma string com um espaço pra satisfazer o endpoint sem influenciar o comportamento.