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로 다시 요청했다.
- 채팅 요청을 스트리밍 없이 보냈다가 거부당한 뒤에야 스트리밍으로 다시 보냈다.
그래서 이미 로그인한 상태에서도 새로고침 버튼은 다시 로그인하라고 안내했다.
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을 받는다.