- PHASE.md 상태를 [진행중]에서 [검토중]으로 전환 - Milestone: 완료 리뷰 업데이트, dev gx10 동등 환경 smoke 검증을 완료 근거로 추가 - SDD: External Provider에 dev gx10 Ornith/vLLM 추가, S10 시나리오와 Evidence Map 동기화
10 KiB
10 KiB
SDD: OpenAI-compatible Provider Passthrough 계약 동기화
위치
- Milestone: Milestone 문서
- Phase: PHASE.md
상태
[승인됨]
SDD 잠금
- 상태: 해제
- 사용자 리뷰: 없음
- 잠금 항목:
- 없음
문제 / 비목표
- 문제: 현재 코드에는 caller metadata로 응답 경로를 선택하는 과거 설계와 provider-native OpenAI-compatible payload를 Edge가 제한하거나 IOP 확장 field로 치환하는 흐름이 남아 있다. 사용자 설계 의도는
model이 가리키는 provider capability가 passthrough/normalized 경로를 결정하고, OpenAI-compatible provider에서는 provider request surface를 그대로 보존하는 것이다. - 비목표:
- 새 route scorer 또는 hybrid local/cloud routing policy 구현
- provider runtime launch/restart option 변경
- output validation filter의 schema/repair policy 구현
- archive 문서의 과거 결정 기록 재작성
Source of Truth
| 영역 | 기준 | 메모 |
|---|---|---|
| Roadmap | Milestone 문서 | 목표, 범위, 기능 Task, 완료 evidence 기준 |
| Outer Contract | openai-compatible-api.md | OpenAI-compatible public request/response 계약 |
| Inner Wire Contract | edge-node-runtime-wire.md | Edge-Node provider tunnel body/frame 책임 |
| Code | apps/edge/internal/openai, apps/edge/internal/service, apps/node/internal/adapters/openai_compat |
구현 source of truth |
| External Provider | dev-corp Spark Ornith/vLLM provider 또는 dev gx10 Ornith/vLLM provider | provider-native field passthrough smoke 대상. 사용자가 dev gx10 동등 검증을 허용했다. |
| User Decision | 현재 사용자 설계 의도 | model 기반 route, metadata known-key read-only 발췌, provider-native payload 보존 |
State Machine
| 상태 | 진입 조건 | 다음 상태 | 근거 |
|---|---|---|---|
| request-received | Edge OpenAI-compatible endpoint가 JSON body를 수신한다 | route-resolved 또는 invalid-request | model envelope parse |
| route-resolved | request model이 route catalog 또는 provider-pool model group에 매칭된다 |
metadata-observed | selected provider capability |
| metadata-observed | route 결정 후 metadata가 있으면 known-key를 내부 문맥으로 복사한다 | provider-passthrough 또는 normalized-dispatch | read-only extraction, route/response path 불변 |
| provider-passthrough | selected provider가 OpenAI-compatible 호출 방식을 지원한다 | provider-response-relayed 또는 provider-error-relayed | ProviderTunnelRequest/ProviderTunnelFrame |
| normalized-dispatch | selected provider/backend가 normalized adapter 실행을 요구한다 | normalized-response-built 또는 run-error | RunRequest/RunEvent |
| provider-response-relayed | provider가 HTTP/SSE 성공 응답을 반환한다 | terminal success | provider status/header/body relay |
| provider-error-relayed | provider가 HTTP error 또는 tunnel error를 반환한다 | terminal error | provider status/body 또는 tunnel error |
Interface Contract
- 계약 원문: openai-compatible-api.md
- 입력:
model: route/provider capability 선택의 1차 source of truthmessages또는input: endpoint별 OpenAI-compatible request payloadmetadata: IOP known-key를 read-only로 발췌하는 container. route/response selector가 아니다.- provider-native payload: selected provider가 지원하는 OpenAI-compatible 표준 field, extension field, 중첩 값. Edge passthrough 경로에서 보존한다.
- 출력:
- provider-passthrough: provider HTTP status/header/body를 relay한다. Chat Completions의 top-level model echo는 alias 보정을 할 수 있다.
- normalized-dispatch: normalized adapter 결과를 OpenAI-compatible response shape로 구성한다.
- metrics/log: provider usage 후보와 IOP known-key 관측은 internal metric/log로 남긴다.
- 금지:
- caller metadata로 passthrough/normalized/response shape를 선택하게 하지 않는다.
- OpenAI-compatible provider passthrough body에 IOP marker/event/envelope를 주입하지 않는다.
- Edge allowlist로 provider-native OpenAI-compatible extension field를 거부하지 않는다.
- IOP 확장 field가 caller의 provider-native field를 삭제하거나 대체하지 않는다.
- metadata known-key 발췌 과정에서 원본 provider payload를 strip/mutate하지 않는다.
Acceptance Scenarios
| ID | Milestone Task | Given | When | Then |
|---|---|---|---|---|
| S01 | selector-remove |
caller가 metadata 안에 임의 response selector로 보일 수 있는 key를 넣는다 | Edge가 OpenAI-compatible request를 처리한다 | 해당 key는 route selector로 해석되지 않고, provider-passthrough body를 바꾸지 않는다 |
| S02 | model-route |
request model이 OpenAI-compatible provider를 가리킨다 |
Chat Completions 또는 Responses를 호출한다 | Edge는 provider tunnel passthrough를 사용한다 |
| S03 | model-route |
request model이 CLI/Ollama/native normalized backend를 가리킨다 |
Chat Completions 또는 Responses를 호출한다 | Edge는 normalized RunRequest path를 사용한다 |
| S04 | metadata-known |
request metadata에 workspace/task/principal 관련 known key와 임의 key가 섞여 있다 | Edge가 route를 결정한 뒤 metadata를 처리한다 | known key는 내부 문맥으로 복사되고 원본 metadata payload는 제거/변형되지 않으며 임의 key는 route/response path를 바꾸지 않는다 |
| S05 | field-preserve |
provider-pool 또는 direct OpenAI-compatible Chat request가 chat_template_kwargs와 임의 provider extension field를 포함한다 |
Edge가 provider tunnel body를 만든다 | provider request body에는 model rewrite 외 field와 중첩 값이 보존된다 |
| S06 | provider-error |
provider가 특정 extension field를 지원하지 않아 HTTP error를 반환한다 | Edge가 provider response를 relay한다 | caller는 provider status/body를 받으며 Edge가 자체 unsupported error로 선변환하지 않는다 |
| S07 | policy-priority |
caller가 provider-native thinking field를 명시한다 | catalog generation policy 또는 IOP think 확장 처리가 실행된다 | caller provider-native field가 삭제되거나 대체되지 않는다 |
| S08 | contract-sync |
구현이 완료된다 | 계약/문서/로드맵 최신 문서를 검색한다 | archive를 제외한 최신 문서에는 public response selector field/모드 설명이 없다 |
| S09 | go-tests |
코드 변경이 완료된다 | 관련 Go 테스트를 실행한다 | Edge OpenAI handler, service provider-pool, Node OpenAI adapter 테스트가 통과한다 |
| S10 | devcorp-smoke |
dev-corp Spark Ornith 또는 dev gx10 Ornith provider가 IOP OpenAI-compatible route에 연결되어 있다 | chat_template_kwargs.enable_thinking=false 요청을 direct provider와 IOP 경유로 각각 1회 호출한다 |
provider-native think-off 동작과 일치하는 빠른 content-first 응답을 관찰하고 reasoning chunk가 생성되지 않는다 |
Evidence Map
| Scenario | Required Evidence | agent-task 연결 |
완료 Evidence 기대 |
|---|---|---|---|
| S01 | selector metadata negative test, request body fixture | agent-task/m-openai-compatible-provider-passthrough-contract-sync/... |
Roadmap Completion에 selector-remove와 test name |
| S02 | OpenAI-compatible provider route unit test | agent-task/m-openai-compatible-provider-passthrough-contract-sync/... |
Roadmap Completion에 model-route와 provider tunnel dispatch evidence |
| S03 | normalized backend route unit test | agent-task/m-openai-compatible-provider-passthrough-contract-sync/... |
Roadmap Completion에 model-route와 normalized dispatch evidence |
| S04 | metadata known-key parsing and body immutability test | agent-task/m-openai-compatible-provider-passthrough-contract-sync/... |
Roadmap Completion에 metadata-known, route-stability, body immutability evidence |
| S05 | provider tunnel body preservation test | agent-task/m-openai-compatible-provider-passthrough-contract-sync/... |
Roadmap Completion에 field-preserve와 captured body fixture |
| S06 | fake provider error relay test | agent-task/m-openai-compatible-provider-passthrough-contract-sync/... |
Roadmap Completion에 provider-error와 status/body relay fixture |
| S07 | generation policy/provider-native priority test | agent-task/m-openai-compatible-provider-passthrough-contract-sync/... |
Roadmap Completion에 policy-priority와 body diff evidence |
| S08 | rg evidence over non-archive docs/contracts/roadmap |
agent-task/m-openai-compatible-provider-passthrough-contract-sync/... |
Roadmap Completion에 contract-sync와 command output summary |
| S09 | Go test command output | agent-task/m-openai-compatible-provider-passthrough-contract-sync/... |
Roadmap Completion에 go-tests와 pass summary |
| S10 | dev-corp 또는 dev gx10 single-call smoke output summary | agent-task/m-openai-compatible-provider-passthrough-contract-sync/... 또는 수동 검증 evidence |
Roadmap Completion 또는 Milestone 완료 리뷰에 devcorp-smoke, direct/IOP first content latency, reasoning/content observation, IOP selected provider evidence |
Cross-repo Dependencies
- 없음
Drift Check
- Milestone 기능 Task와 Acceptance Scenario가 일치한다.
- Evidence Map이 code-review/complete.log에서 검증 가능하다.
- agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
- 사용자 리뷰가 필요한 항목은
USER_REVIEW.md에만 남겼다.
사용자 리뷰 이력
- 없음
작업 컨텍스트
- 표준선: OpenAI-compatible provider 경로는 provider-compatible proxy처럼 동작하고, provider-native field 판단은 provider에 맡긴다.
- 표준선:
model이 route source of truth이며, metadata는 IOP known-key를 read-only로 발췌하는 container다. - 표준선: provider tunnel body는
modelserved target rewrite와 auth/header 처리 외에는 caller/provider request surface와 중첩 값을 보존한다. - 후속 SDD: 없음