2026-09-09

tars의 ChatGPT Codex 모델 경로 수정

tars 개발을 main에서 다시 시작했다. 계기는 linetta였다. linetta에서 ChatGPT Codex로 로그인한 뒤 모델 옆 새로고침을 누르면 다시 로그인하라는 안내가 나왔는데, 원인이 tars 쪽에 있었다. tars에 이슈를 올리려고 보니 저장소를 보관 처리해 둔 상태라 읽기 전용이었다. linetta가 모델 목록을 직접 돌려주거나 tars를 포크하는 방법도 적어 뒀지만, 10분 뒤 보관 안내를 내리고 tars에서 원인을 직접 고쳤다. 재시작 후 첫 수정은 이틀 동안 태그 세 개로 나갔다.

문제

ChatGPT Codex 로그인으로 연결 테스트와 채팅은 됐지만 모델 목록 새로고침은 실패했다. linetta가 실제 ChatGPT 계정으로 이 경로를 처음 돌렸을 때 연결 테스트 한 번에 문제 세 개가 함께 드러났다.

  • FetchModels가 ChatGPT OAuth bearer로 OpenAI 플랫폼의 /v1/models를 호출했고, 이 호스트는 401을 돌려준다.
  • 클라이언트는 401을 토큰 만료로 판단해 유효한 refresh token을 쓰고, 같은 잘못된 URL로 다시 요청했다.
  • 채팅 요청을 스트리밍 없이 보냈다가 거부당한 뒤에야 스트리밍으로 다시 보냈다.

그래서 이미 로그인한 상태에서도 새로고침 버튼은 다시 로그인하라고 안내했다.

모델 목록 요청이 잘못된 주소로 가서 401이 나고, refresh token을 쓴 뒤 다시 로그인하라는 안내로 끝나는 흐름

linetta 쪽에서는 처음에 ChatGPT 백엔드에 모델 목록 엔드포인트가 없다고 봤고, Codex CLI도 목록을 하드코딩한다고 생각했다. 모델 이름을 직접 넣어 보니 gpt-5.6은 400, gpt-5.6-sol은 통과해서 어떤 이름이 되는지 앱 안에서 알 방법이 없었다. 알고 보니 Codex CLI가 쓰는 백엔드에 /codex/models 엔드포인트가 있었고, 응답 형식은 ~/.codex/models_cache.json과 Codex CLI 소스에서 확인했다.

수정

v0.36.0에서 세 가지를 고쳤다.

  • 모델 목록 요청을 Codex CLI가 쓰는 ChatGPT Codex 백엔드로 보낸다.
  • 첫 요청부터 스트리밍한다. 이 백엔드는 스트리밍이 아닌 채팅 요청을 거부한다.
  • 기본 모델을 gpt-5.3-codex에서 gpt-5.6-sol로 바꿨다.

v0.36.0을 linetta에 올리자 linetta의 의존성 검사에 걸렸다. linetta 엔진은 tars의 pkg/session을 쓰지 못하게 막아 두는데, 새 버전이 그 패키지를 끌어왔고 이를 떼어 낸 뒤에도 검사가 한 번 더 실패했다. v0.37.0은 이 의존성을 정리한 릴리스다.

v0.37.1에서는 v0.36.0에서 내린 판단 하나를 뒤집었다. v0.36.0은 Codex CLI 버전을 흉내 내지 않고 tars 자신의 빌드 버전을 client_version으로 보냈다. 이 값이 호출자 이름표라고 봤는데, 백엔드는 이를 호환성 하한선으로 읽었다. linetta처럼 tars를 라이브러리로 쓰면 빌드 버전이 채워지지 않아 dev가 나가고, 백엔드는 이를 400으로 거부했다. tars 릴리스 버전 0.37.0을 보내도 빈 목록이 돌아왔다. 2026-09-09에 값을 바꿔 가며 확인해 보니 0.147.0에서 모델 5개, 0.153.4 이상에서 6개가 나와서 실제 Codex CLI 버전 0.153.4로 고정했다.

설치

tars.marvin-42.com에서 설치하거나 releases에서 v0.37.1을 받는다.

같은 작업대에서 나온 이웃 도구입니다.