Skip to content

feat(sidecar): unify web-search and vision sidecar selection (auth slot + picker/probe filters) #2188

Description

@lidge-jun

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 / findAnthropicVisionProvideradapter === "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-40BASELINE_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다.

거름망 (순서 고정)

  1. Codex 피커에 나타나기로 한 모델.
    피커 집합은 visibleNativeSlugs / desktopVisibleNativeSlugs (src/codex/catalog/metadata.ts:331, :371)와 관리 UI의 listManagementModelRows (src/server/management/model-rows.ts:50)다. disabledModels에 가려진 줄은 여기서 탈락한다. 예외는 위 Luna/Haiku auth 슬롯뿐이다.
  2. 라이브 프로브가 통과하고, 이 레포에 실행 로직이 들어온 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). 비전처럼 거절 게이트가 없다.

비전 사이드카

프로브 없음. 거름망만.

  1. Codex 피커에 나타나기로 한 모델 — 웹서치 1번과 같은 집합 (listManagementModelRows / visibleNativeSlugs). auth 시 Luna/Haiku는 여기 없어도 남긴다.
  2. text-only를 비전 로직에서 제외.
    이미 조각이 있다. isModelTextOnly (src/vision/index.ts:29-36)는 noVisionModels이거나 modelInputModalitiesimage가 없으면 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesttoolstool_calls, MCP, web-search / sidecar tools

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions