Why
웹서치 사이드카와 비전 사이드카가 백엔드를 openai | anthropic 두 칸으로만 나누고, "Codex 전체 / Claude 전체"를 후보로 펼친다. 그 전제는 이미 깨져 있다.
이 이슈가 #414 #415 #1616 #1937을 대체한다. 백엔드를 Exa/Zen/Doubao로 하나씩 더하는 방식이 아니라, 선택 규칙을 먼저 고친다.
Auth (전역)
구현은 전역 두 플래그로 시작한다. 이름은 구현에서 isCodexAuth / isAnthropicAuth로 고정한다.
현재 코드에 이미 조각이 있다. 한곳으로 모은다.
- Codex/ChatGPT:
listOpenAiForwardSidecarCandidates (src/providers/openai-sidecar.ts) + forward authMode + 로그인된 ChatGPT 계정. planWebSearch openai 분기는 openAiSidecar가 없으면 계획이 없다 (src/web-search/index.ts:192-193).
- Anthropic:
findAnthropicSidecarProvider / findAnthropicVisionProvider — adapter === "anthropic" + authMode === "oauth" + active account needsReauth !== true (src/web-search/index.ts:87-96, src/vision/index.ts:220-226).
isCodexAuth === true이면 gpt-5.6-luna는 모델 설정/피커에서 꺼져 있어도 웹서치·비전 후보에 남긴다. isAnthropicAuth === true이면 claude-haiku-4-5(현 baseline)도 같다.
지금 비전 쪽 baseline은 src/vision/eligibility.ts:37-40의 BASELINE_VISION_MODELS다 (openai: gpt-5.6-luna, anthropic: claude-haiku-4-5). 웹서치 기본 모델은 src/web-search/index.ts:14-16 (gpt-5.6-luna / claude-sonnet-5). 웹서치 Anthropic 기본값을 Haiku로 맞출지, Sonnet을 유지할지는 구현 PR에서 정하되, auth만으로 여는 고정 슬롯은 Luna와 Haiku다.
웹서치 사이드카
선행: 프로바이더 × 프로토콜 조사
아무 채팅 모델이나 webSearchSidecar.backend에 넣지 않는다. 서버가 검색을 실행하는 도구/엔드포인트가 있는 경우만 후보가 된다.
2026-08-20 조사로 확인한 후보군 (라이브 프로브 전, 문서 기준):
| 후보 |
프로토콜 |
도구/엔드포인트 |
비고 |
| ChatGPT / Codex (현 openai 백엔드) |
Responses |
{ type: "web_search" } |
이미 src/web-search/executor.ts가 {baseUrl}/responses로 보낸다. Codex CLI는 cached/live web_search. |
| Claude (현 anthropic 백엔드) |
Messages |
web_search_20250305 / 최신 web_search_20260209 |
src/web-search/anthropic-executor.ts. Bedrock에는 없음. |
| Gemini |
Gemini / Interactions |
google_search (구 google_search_retrieval) |
Grounding with Google Search. 인용/groundingMetadata. API 키. 검색+다른 툴 동시 제한이 문서에 있음. |
| xAI Grok |
Responses |
{ type: "web_search" } |
docs.x.ai/developers/tools/web-search. 옛 Live Search는 2026-01 deprecate. allowed_domains / excluded_domains. |
| OpenCode Zen / opencode-go |
Responses |
hosted web_search |
#1616이 2026-08-13에 POST …/zen/go/v1/responses + web_search_call 확인. ChatGPT 쿼터 안 씀. |
| Exa 등 전용 검색 벤더 |
자체 Search API |
검색 JSON → SidecarOutcome 매핑 |
#414. LLM이 아님. 프로브 대상은 "호스트된 검색 도구를 가진 LLM"과 별선. |
이 표는 후보일 뿐 구현 허가가 아니다. 라이브 프로브가 성공하고, 실행 로직이 들어온 뒤에만 active다.
거름망 (순서 고정)
- Codex 피커에 나타나기로 한 모델.
피커 집합은 visibleNativeSlugs / desktopVisibleNativeSlugs (src/codex/catalog/metadata.ts:331, :371)와 관리 UI의 listManagementModelRows (src/server/management/model-rows.ts:50)다. disabledModels에 가려진 줄은 여기서 탈락한다. 예외는 위 Luna/Haiku auth 슬롯뿐이다.
- 라이브 프로브가 통과하고, 이 레포에 실행 로직이 들어온 active 모델만.
문서에 도구가 있다고 피커에 올리지 않는다. Gemini google_search, Grok web_search, Zen hosted web_search는 각각 프로브 + executor가 생긴 뒤에만 2번 망을 통과한다.
GUI에서 설정 가능한 웹서치 사이드카 모델 = 1 ∩ 2 (+ auth 시 Luna/Haiku). CLI 커맨드도 같은 집합을 쓴다.
개편이 필요한 현재 로직
OcxWebSearchSidecarConfig.backend가 "openai" | "anthropic"만 받는다 (src/types/config.ts:787-796). resolveSidecarBackend는 explicit anthropic이 아니면 무조건 openai (src/web-search/index.ts:104-108). types 주석은 "unset이면 anthropic 우선"인데 코드와 어긋난다.
- 실행기도 두 개다.
runWebSearch (ChatGPT forward /responses)와 runAnthropicWebSearch. keyed/Gemini/Grok 경로가 없다.
- 라우티드 프로바이더의 hosted
web_search는 파서에서 걷어지고 사이드카로 치환된다. 그 "Codex 전체 / Claude 전체 중 하나를 빌린다"는 모델이 개편 대상이다.
- 관리 API는
PUT으로 webSearch.model 문자열을 거의 그대로 넣는다 (src/server/management/config-routes.ts:604-606). 비전처럼 거절 게이트가 없다.
비전 사이드카
프로브 없음. 거름망만.
- Codex 피커에 나타나기로 한 모델 — 웹서치 1번과 같은 집합 (
listManagementModelRows / visibleNativeSlugs). auth 시 Luna/Haiku는 여기 없어도 남긴다.
- text-only를 비전 로직에서 제외.
이미 조각이 있다. isModelTextOnly (src/vision/index.ts:29-36)는 noVisionModels이거나 modelInputModalities에 image가 없으면 true. modelAcceptsImageInput / isVisionEligibleModel (src/vision/eligibility.ts:112-147)은 "text-only로 증명되면 탈락, unknown은 통과"다.
GUI에 보여줄 값은 1번을 통과한 뒤 2번으로 한 번 더 거른 집합이다. "unknown이라서 통과"를 피커에 펼치지 말고, 피커에 있는 줄만 2번에 넣는다.
개편이 필요한 현재 로직
visionEligibleModelOptions (src/vision/eligibility.ts:201-229)는 enabled 백엔드의 전체 catalog candidate + baseline을 펼친다. 사실상 Codex 전체 / Claude 전체다. 피커 가시성과 분리되어 있지 않다.
visionCandidateRows (src/server/management/vision-sidecar-options.ts:45-56)는 listManagementModelRows에서 disabled !== true만 본다. 피커 정책과 거의 같지만, auth-only Luna/Haiku와 "피커에 나타나기로 한 모델"을 한 함수로 고정하지 않았다.
- 디스크라이버 실행은 여전히
vision/describe.ts가 ChatGPT forwardProvider.baseUrl/responses로만 가거나 Anthropic OAuth Messages로만 간다. #1937의 Doubao/volcengine 디스크라이버는 이 이슈의 2번 망을 통과한 뒤에만 후속이다. 이번 이슈는 선택 규칙을 먼저 고친다.
resolveVisionBackend는 unset이면 Anthropic credential이 있을 때 anthropic (src/vision/index.ts:229-235). 웹서치 resolveSidecarBackend와 반대다. 전역 isCodexAuth / isAnthropicAuth로 맞춘다.
GUI / CLI
- GUI: 지금 대시보드 사이드카 칸 (
gui + PUT /api/sidecar-settings, config-routes.ts webSearch/vision). 옵션 리스트를 위 거름망 결과만 보여 준다.
- CLI: 같은 집합을 쓰는 설정 커맨드를 만든다 (예:
ocx sidecar web-search …, ocx sidecar vision …). GUI만 열려 있고 CLI가 우회하면 거름망이 아니다.
- 쓰기 게이트와 제안 리스트를 같은 함수에서 나온다. 비전의
visionDescriberIsProvablyBlind (vision-sidecar-options.ts:94)처럼, 웹서치도 리스트에 없는 모델을 persist하지 않는다. 예외는 auth 슬롯 Luna/Haiku.
하지 않는 것
Acceptance
Why
웹서치 사이드카와 비전 사이드카가 백엔드를
openai | anthropic두 칸으로만 나누고, "Codex 전체 / Claude 전체"를 후보로 펼친다. 그 전제는 이미 깨져 있다.이 이슈가 #414 #415 #1616 #1937을 대체한다. 백엔드를 Exa/Zen/Doubao로 하나씩 더하는 방식이 아니라, 선택 규칙을 먼저 고친다.
Auth (전역)
구현은 전역 두 플래그로 시작한다. 이름은 구현에서
isCodexAuth/isAnthropicAuth로 고정한다.현재 코드에 이미 조각이 있다. 한곳으로 모은다.
listOpenAiForwardSidecarCandidates(src/providers/openai-sidecar.ts) + forwardauthMode+ 로그인된 ChatGPT 계정.planWebSearchopenai 분기는openAiSidecar가 없으면 계획이 없다 (src/web-search/index.ts:192-193).findAnthropicSidecarProvider/findAnthropicVisionProvider—adapter === "anthropic"+authMode === "oauth"+ active accountneedsReauth !== true(src/web-search/index.ts:87-96,src/vision/index.ts:220-226).isCodexAuth === true이면gpt-5.6-luna는 모델 설정/피커에서 꺼져 있어도 웹서치·비전 후보에 남긴다.isAnthropicAuth === true이면claude-haiku-4-5(현 baseline)도 같다.지금 비전 쪽 baseline은
src/vision/eligibility.ts:37-40의BASELINE_VISION_MODELS다 (openai: gpt-5.6-luna,anthropic: claude-haiku-4-5). 웹서치 기본 모델은src/web-search/index.ts:14-16(gpt-5.6-luna/claude-sonnet-5). 웹서치 Anthropic 기본값을 Haiku로 맞출지, Sonnet을 유지할지는 구현 PR에서 정하되, auth만으로 여는 고정 슬롯은 Luna와 Haiku다.웹서치 사이드카
선행: 프로바이더 × 프로토콜 조사
아무 채팅 모델이나
webSearchSidecar.backend에 넣지 않는다. 서버가 검색을 실행하는 도구/엔드포인트가 있는 경우만 후보가 된다.2026-08-20 조사로 확인한 후보군 (라이브 프로브 전, 문서 기준):
{ type: "web_search" }src/web-search/executor.ts가{baseUrl}/responses로 보낸다. Codex CLI는 cached/liveweb_search.web_search_20250305/ 최신web_search_20260209src/web-search/anthropic-executor.ts. Bedrock에는 없음.google_search(구google_search_retrieval)groundingMetadata. API 키. 검색+다른 툴 동시 제한이 문서에 있음.{ type: "web_search" }allowed_domains/excluded_domains.web_searchPOST …/zen/go/v1/responses+web_search_call확인. ChatGPT 쿼터 안 씀.SidecarOutcome매핑이 표는 후보일 뿐 구현 허가가 아니다. 라이브 프로브가 성공하고, 실행 로직이 들어온 뒤에만 active다.
거름망 (순서 고정)
피커 집합은
visibleNativeSlugs/desktopVisibleNativeSlugs(src/codex/catalog/metadata.ts:331,:371)와 관리 UI의listManagementModelRows(src/server/management/model-rows.ts:50)다.disabledModels에 가려진 줄은 여기서 탈락한다. 예외는 위 Luna/Haiku auth 슬롯뿐이다.문서에 도구가 있다고 피커에 올리지 않는다. Gemini
google_search, Grokweb_search, Zen hostedweb_search는 각각 프로브 + executor가 생긴 뒤에만 2번 망을 통과한다.GUI에서 설정 가능한 웹서치 사이드카 모델 = 1 ∩ 2 (+ auth 시 Luna/Haiku). CLI 커맨드도 같은 집합을 쓴다.
개편이 필요한 현재 로직
OcxWebSearchSidecarConfig.backend가"openai" | "anthropic"만 받는다 (src/types/config.ts:787-796).resolveSidecarBackend는 explicit anthropic이 아니면 무조건 openai (src/web-search/index.ts:104-108). types 주석은 "unset이면 anthropic 우선"인데 코드와 어긋난다.runWebSearch(ChatGPT forward/responses)와runAnthropicWebSearch. keyed/Gemini/Grok 경로가 없다.web_search는 파서에서 걷어지고 사이드카로 치환된다. 그 "Codex 전체 / Claude 전체 중 하나를 빌린다"는 모델이 개편 대상이다.PUT으로webSearch.model문자열을 거의 그대로 넣는다 (src/server/management/config-routes.ts:604-606). 비전처럼 거절 게이트가 없다.비전 사이드카
프로브 없음. 거름망만.
listManagementModelRows/visibleNativeSlugs). auth 시 Luna/Haiku는 여기 없어도 남긴다.이미 조각이 있다.
isModelTextOnly(src/vision/index.ts:29-36)는noVisionModels이거나modelInputModalities에image가 없으면 true.modelAcceptsImageInput/isVisionEligibleModel(src/vision/eligibility.ts:112-147)은 "text-only로 증명되면 탈락, unknown은 통과"다.GUI에 보여줄 값은 1번을 통과한 뒤 2번으로 한 번 더 거른 집합이다. "unknown이라서 통과"를 피커에 펼치지 말고, 피커에 있는 줄만 2번에 넣는다.
개편이 필요한 현재 로직
visionEligibleModelOptions(src/vision/eligibility.ts:201-229)는 enabled 백엔드의 전체 catalog candidate + baseline을 펼친다. 사실상 Codex 전체 / Claude 전체다. 피커 가시성과 분리되어 있지 않다.visionCandidateRows(src/server/management/vision-sidecar-options.ts:45-56)는listManagementModelRows에서disabled !== true만 본다. 피커 정책과 거의 같지만, auth-only Luna/Haiku와 "피커에 나타나기로 한 모델"을 한 함수로 고정하지 않았다.vision/describe.ts가 ChatGPTforwardProvider.baseUrl/responses로만 가거나 Anthropic OAuth Messages로만 간다. #1937의 Doubao/volcengine 디스크라이버는 이 이슈의 2번 망을 통과한 뒤에만 후속이다. 이번 이슈는 선택 규칙을 먼저 고친다.resolveVisionBackend는 unset이면 Anthropic credential이 있을 때 anthropic (src/vision/index.ts:229-235). 웹서치resolveSidecarBackend와 반대다. 전역isCodexAuth/isAnthropicAuth로 맞춘다.GUI / CLI
gui+PUT /api/sidecar-settings,config-routes.tswebSearch/vision). 옵션 리스트를 위 거름망 결과만 보여 준다.ocx sidecar web-search …,ocx sidecar vision …). GUI만 열려 있고 CLI가 우회하면 거름망이 아니다.visionDescriberIsProvablyBlind(vision-sidecar-options.ts:94)처럼, 웹서치도 리스트에 없는 모델을 persist하지 않는다. 예외는 auth 슬롯 Luna/Haiku.하지 않는 것
Acceptance
isCodexAuth/isAnthropicAuth가 한곳에서 계산되고 웹서치·비전이 공유한다.backend: "openai" | "anthropic"만으로 Codex 전체/Claude 전체를 펼치는 경로가 관리 API와 CLI에서 사라진다.