iop/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/inference-api-surface-execution-lifecycle-refactor.md
toki ad70fcb46e fix(edge): agy 도구 연속 호출을 지원한다
공식 agy의 model-role functionResponse를 Chat tool 메시지로 변환한다.
원격 벤치 검증 기록과 후속 API surface 리팩터링 계획을 함께 반영한다.
2026-08-13 23:25:39 +09:00

99 lines
9.5 KiB
Markdown

# Milestone: [surface-01] Inference API Surface와 실행 Lifecycle 책임 경계 리팩터링
## 위치
- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
- Phase: [PHASE.md](../PHASE.md)
## 목표
OpenAI Chat/Responses, Anthropic Messages, Gemini ingress의 서로 다른 외부 계약은 surface별 adapter가 소유하고, 인증 이후 provider admission·dispatch·attempt·cancel은 기존 `runService`/`SubmitProviderPool` 경계를 재사용한다. Protocol별 실행 준비와 endpoint commit·terminal·usage projection은 각 기존 runtime에 남겨 단계별 소유권을 명확히 한다.
현재 외부 응답과 provider-native option 전달을 보존하면서 Gemini의 Chat handler 내부 HTTP 재진입과 surface/lifecycle 책임 혼재를 제거해, 이후 provider 보완이 다른 API surface에 미치는 회귀 범위를 줄인다.
## 상태
[계획]
## 승격 조건
- 없음
## 구현 잠금
- 상태: 잠금
- SDD: 필요
- SDD 문서: [SDD.md](../../../sdd/knowledge-tool-optimization-extension/inference-api-surface-execution-lifecycle-refactor/SDD.md)
- SDD 사유: 세 외부 API 계약과 stream lifecycle, cross-repo benchmark baseline을 함께 보존해야 하는 경계 리팩터링이다.
- SDD 상태: 승인됨
- SDD 잠금: 해제
- SDD 사용자 리뷰: 없음
- 잠금 해제 조건: 아래 체크리스트
- [x] SDD 잠금이 해제되어 있다.
- [x] SDD 사용자 리뷰가 없거나 승인/해결되었다.
- [x] Acceptance Scenario가 Milestone 기능 Task와 연결되어 있다.
- [x] Evidence Map이 완료 시 `complete.log``milestone-task` id별 집계와 최종 검증 evidence로 검증 가능하게 연결되어 있다.
- [ ] workspace lock `iop:inference-api-surface-execution-lifecycle-refactor`의 모든 의존 상태가 `enable`이다.
- [ ] 구현 plan 시작 시 `iop-s0` 벤치마크 이후 변경을 제품 code/spec/contract와 benchmark-only harness/data로 분류하고, 제품 동작에 필요한 변경만 현재 `dev`에 반영됐거나 명시적으로 제외됐는지 확인한 뒤 baseline을 고정한다.
- 결정 필요: 없음
## 범위
- 리팩터링 시작 전 `iop-s0``[bench-02]` 결과, 대상 revision과 그 시점의 API·provider 동작을 baseline으로 고정하고, 제품 변경과 benchmark-only 변경을 분리한 외부 계약별 characterization matrix를 만든다.
- OpenAI Chat/Responses, Anthropic Messages, Gemini `streamGenerateContent`가 credential header 추출, request decode·validation, wire error·response/SSE projection을 각 surface에서 계속 소유하되 기존 공통 principal/projection resolver는 중복 구현하지 않도록 책임 지도를 고정한다.
- provider admission·dispatch·attempt attribution·Node cancellation은 기존 `runService`, `SubmitProviderPool`, `SubmitProviderTunnel`을 source of truth로 유지한다. 새 all-surface service interface는 기존 capability의 구체적 결손이 characterization으로 확인된 경우에만 허용한다.
- surface validation 이후 protocol별 실행 준비, provider execution, pre-commit/commit, endpoint terminal과 usage finalization의 단계별 소유자를 명시한다. Stream Evidence Gate와 single-request coordinator의 기존 terminal state machine은 대체하지 않는다.
- Gemini ingress가 내부 `http.Request`/`ResponseWriter`를 합성해 `handleChatCompletions`로 재진입하지 않고, 검증된 Gemini→Chat 변환 결과로 operation-specific 실행 함수와 기존 service capability를 직접 사용하도록 변경한다.
- raw passthrough의 unknown/provider-native field와 translated Gemini `extra_body.google.thinking_config`가 model rewrite 이후에도 손실되지 않도록 보존 경계를 검증한다.
- 이미 올바르게 분리된 handler·codec은 이동하지 않고 cross-surface handler 호출이나 중복 lifecycle 소유권이 확인된 경로만 단계적으로 수정한다.
## 기능
### Epic: [architecture-baseline] 동작 baseline과 책임 경계 고정
리팩터링이 공통 API 스키마 설계가 아니라 외부 동작 보존과 내부 책임 분리임을 먼저 고정한다.
- [ ] [baseline-freeze] `iop-s0` `[bench-02]``[검토중]` 또는 `[완료]`로 진입한 시점의 호출 matrix와 revision을 기록하고 제품 code/spec/contract delta와 benchmark-only harness/data delta를 분리한다. 현재 `dev`에 반영할 제품 delta, 명시적 제외 근거, direct·single-request terminal과 provider-native option characterization을 baseline으로 고정한다. 검증: benchmark report/evidence 포인터, 양쪽 commit과 대상 workspace lock `true`를 확인한다.
- [ ] [boundary-map] OpenAI Chat/Responses, Anthropic Messages, Gemini ingress별 credential 추출·decode·validation·execution preparation·provider execution·wire projection·terminal 소유권과 허용 의존 방향을 확정한다. 공통 principal resolver, 기존 service와 endpoint runtime의 재사용 지점을 함께 표시한다.
### Epic: [execution-boundary] Surface와 실행 lifecycle 분리
API별 wire 형식과 terminal state machine은 합치지 않고, 기존 provider service 경계를 재사용하며 cross-surface handler 결합만 제거한다.
- [ ] [execution-entrypoint] 기존 `runService`/`SubmitProviderPool`을 재사용하는 operation-specific ingress 실행 함수를 추출해 Gemini의 Chat handler 내부 HTTP 재진입을 제거한다. 새 service-wide port는 기존 capability 결손 evidence가 있을 때만 추가한다. 검증: production Gemini 경로에서 `handleChatCompletions` 재호출이 없고 direct/preset dispatch 결과가 baseline과 같다.
- [ ] [surface-adapters] OpenAI Chat/Responses, Anthropic Messages, Gemini의 request codec, validation, error envelope, JSON/SSE projector가 surface별 계약 타입과 정책을 독립적으로 소유하도록 cross-surface handler 의존을 제거한다. 이미 분리된 경로의 package/file 재배치는 요구하지 않는다.
- [ ] [lifecycle-owner] provider admission·attempt·cancel은 service, pre-commit·commit·endpoint terminal은 기존 endpoint runtime/Stream Evidence Gate/single-request coordinator가 소유하도록 단계별 single-owner 규칙을 고정한다. 검증: 정상·provider 오류·pre/post-commit 오류·timeout·caller cancel matrix에서 terminal/usage 중복이 없다.
- [ ] [native-option-preservation] raw passthrough unknown field, Anthropic native body, Gemini translated `extra_body`, model alias rewrite가 기존 provider 실행 경계를 통과해도 보존되도록 lossless 전달과 fail-closed 검증을 적용한다.
### Epic: [behavior-regression] 계약 회귀와 문서 정합성 검증
구조 변화가 caller-visible behavior나 benchmark 조건을 바꾸지 않았음을 증명한다.
- [ ] [contract-regression] OpenAI Chat/Responses, Anthropic Messages, Gemini direct·single-request의 stream/non-stream 해당 조합과 auth/error/tool/reasoning/usage/terminal deterministic characterization test를 통과시킨다. 검증: 관련 Edge package test와 기존 benchmark evidence 비교가 baseline 대비 의도하지 않은 차이 없이 통과한다. 외부 provider live smoke는 별도 환경·비용 승인이 있을 때만 추가하며 완료 필수 조건이 아니다.
- [ ] [spec-sync] 책임 경계와 실제 source path가 확정되면 외부 계약은 동작 변경 없이 source pointer만 필요한 범위에서 갱신하고, `agent-spec`을 최종 구현과 동기화한다. 기존 계약과 다른 제품 동작이 발견되면 이 리팩터링에서 암묵 수정하지 않고 별도 변경 후보로 분리한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: Milestone과 승인된 SDD를 만들었고 실제 리팩터링 및 회귀 evidence는 아직 없다.
- 검토 항목: 없음
- 리뷰 코멘트: 없음
## 범위 제외
- OpenAI, Anthropic, Gemini 요청/응답을 하나의 공통 DTO나 최저공통분모 API로 통합하는 작업
- 외부 endpoint, field, error envelope, SSE event 순서, auth 방식 또는 provider selection 의미 변경
- 신규 provider·protocol 추가, provider 품질/성능 tuning, benchmark runner·fixture·scoring 변경
- Control Plane projection, Edge-Node wire, config/proto schema의 기능 변경
- Stream Evidence Gate 의미 필터, single-request stage 정책, retry/fallback 정책의 신규 기능 추가
- 기존 `runService`/`SubmitProviderPool`과 겹치는 범용 all-surface executor 또는 universal terminal DTO 추가
- 별도 승인 없는 외부 provider live smoke나 전체/부분 benchmark 재실행을 완료 필수 조건으로 두는 작업
- 전체 `apps/edge/internal/openai` package를 한 번에 물리적으로 분할하거나 파일명 정리만을 목적으로 하는 대규모 이동
## 작업 컨텍스트
- 관련 경로: `apps/edge/internal/openai/`, `apps/edge/internal/service/`, `agent-contract/outer/`, `agent-spec/input/openai-compatible-surface.md`
- 표준선: 외부 API는 surface별 anti-corruption adapter로 유지하고, 기존 service의 provider 실행 capability를 재사용한다. 공통화는 검증된 중복과 cross-surface handler 의존에만 적용하며 endpoint-native commit/terminal state machine을 중앙화하지 않는다.
- 실행 순서와 차단 관계: [전역 마일스톤 실행 순서](../../../priority-queue.md)
- 관련 Milestone: [[bench-02] IOP 원샷 Agent 모델 비교 벤치마크](iop-one-shot-agent-model-comparison.md)
- 확인 필요: 구현 시작 시 `iop-s0` 벤치마크 완료 revision과 현재 `dev` drift를 제품 변경/benchmark-only 변경으로 분류하고 제품 baseline의 반영 또는 제외 근거를 남긴다.