Skip to content

fix(editorial-chat): web→api-server only, ai-server gRPC (#446 fixup)#450

Merged
cocoyoon merged 2 commits into
devfrom
fix/editorial-chat-grpc-internal
May 6, 2026
Merged

fix(editorial-chat): web→api-server only, ai-server gRPC (#446 fixup)#450
cocoyoon merged 2 commits into
devfrom
fix/editorial-chat-grpc-internal

Conversation

@cocoyoon
Copy link
Copy Markdown
Member

@cocoyoon cocoyoon commented May 6, 2026

PR #446 의 Stage 3 chat (대화형 매거진 편집) 이 web → ai-server (HTTP) 직접 호출로 구현돼서 모노레포 컨벤션 위반:

  • ai-server 는 internal compute 서비스 (외부 비노출)
  • web 은 항상 api-server (Rust) 만 호출
  • 내부 compute 가 필요한 부분만 api-server → ai-server gRPC

prod 적용 전에 (#446 의 기능 완성 PR 로) fixup.

변경

책임 분리

책임 위치
chat 세션/메시지 CRUD (assets DB) api-server (domains/admin/editorial_article_chat)
admin 인증 게이팅 api-server (기존 admin auth 미들웨어)
한 턴 LLM 실행 (Gemini + tool loop) ai-server (gRPC RunChatTurn, stateless)
layout persist api-server (gRPC 응답의 final_layout_json)

proto

  • inbound.Queue.RunChatTurn(article_id, layout_json, history_json, user_message) → events_json + final_layout_json + final_text + ...
  • 모든 dynamic 페이로드 (layout/history/events/tool_calls/tool_result) 는 JSON string — control-plane RPC 와 달리 free-form 이라 typed proto 의 이득 없음

ai-server

  • editorial_article_chat/api.py 삭제 (HTTP router)
  • editorial_article_chat/repository.py 삭제 (DB layer)
  • agent.run_turn 시그니처 변경: pure compute (article_title + layout + history + user_text → RunTurnResult)
  • ToolExecutor 생성자에서 db 제거, persist_layout 삭제
  • bootstrap.py 의 chat router include 제거
  • MetadataServicer.RunChatTurn 신규

api-server (Rust)

  • 신규 entities: assets_editorial_article_chat_{sessions,messages} (SeaORM)
  • 신규 도메인: domains/admin/editorial_article_chat.rs (4 routes)
    • GET/POST /sessions/{article_id} — 세션 list/create
    • GET/POST /messages/{session_id} — 메시지 list/send
  • gRPC client: run_chat_turn (deadline 120s)
  • send_message 오케스트레이션:
    1. user 메시지 INSERT
    2. article (layout, title) 로드 + history 로드
    3. ai-server gRPC RunChatTurn
    4. events 순서대로 INSERT (assistant + tool 메시지)
    5. layout_changed 면 article UPDATE
    6. session.last_message_at touch

web

  • 2 chat route 가 AI_SERVER_HTTP_URLAPI_BASE_URL + Bearer 패턴으로 (다른 admin proxy 와 동일)
  • lib/server-env.tsAI_SERVER_HTTP_URL export 삭제

마이그 픽스 (포함)

  • supabase/migrations/20260505020001_editorial_articles_published.sqlDROP TABLE IF EXISTS public.editorial_articles CASCADE; 추가 (operation cloud 적용 도중 SQLSTATE 42703 로 실패한 순서 버그 수정)

테스트

로컬

  • cargo build -p api-server clean
  • tsc --noEmit clean (chat 파일)
  • ✅ ai-server import smoke (RunTurnResult, MetadataServicer.RunChatTurn 존재)
  • ✅ gRPC E2E:
    RunChatTurn(layout='Test 매거진' + intro 1개, user='title 을 "K-pop 가을 룩" 으로 바꿔줘')
     → events: [assistant(tool_call=update_title), tool(result), assistant(text)]
     → layout_changed=True, new_title='K-pop 가을 룩'
     → final_text="네, 매거진 제목을 'K-pop 가을 룩'으로 업데이트했습니다."
    

검증 권장 (web UI)

  • admin 매거진 detail → chat 패널 → 새 세션 생성 → 메시지 전송 → ~30s 후 assistant 응답 + layout 반영 확인

Out of scope

Bump

bump:patch (architectural fix without user-facing API change. web ↔ api-server contract: 같은 4 endpoints, 다른 백엔드 구현. ai-server 외부 surface 삭제.)

🤖 Generated with Claude Code

cocoyoon and others added 2 commits May 6, 2026 13:30
#446 의 020001 (publish editorial_articles 생성) 이 020002 (drop staging) 보다
먼저 돌면서 staging 의 editorial_articles 가 살아있는 채로 publish 의 slug 컬럼
인덱스 만들려다 SQLSTATE 42703 (column does not exist) 로 실패. operation cloud
배포 시 발견.

DROP TABLE IF EXISTS public.editorial_articles CASCADE 를 020001 시작 부분에
추가해서 idempotent 하게. 020002 의 동등 로직과 안전 중복.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…#446 fixup)

PR #446 의 Stage 3 chat 이 web → ai-server (HTTP) 직접 호출로 구현돼서 모노레포
컨벤션 위반. ai-server 는 internal compute, web 은 항상 api-server 만 호출.
Prod 배포 전에 같은 스코프 (#446) 안에서 fixup.

책임 분리:
  - api-server: chat session/message CRUD (assets DB), layout persist,
    admin 인증 게이팅 — 새 도메인 `domains/admin/editorial_article_chat`.
  - ai-server: 한 턴 LLM 실행 (Gemini + tool loop) — pure compute,
    gRPC `inbound.Queue/RunChatTurn`. DB 안 만짐.
  - web: 기존 admin proxy 패턴 (`API_BASE_URL` + Bearer token) 으로 통일.

ai-server 정리:
  - editorial_article_chat/api.py 삭제 (HTTP router)
  - editorial_article_chat/repository.py 삭제 (DB layer)
  - agent.run_turn 시그니처 변경: (article_title, layout, history, user_text)
    → RunTurnResult (events list + final_layout + tool_calls_made + ...)
  - ToolExecutor 생성자에서 db 제거, persist_layout 삭제
  - bootstrap.py 의 chat router include 제거
  - MetadataServicer.RunChatTurn 신규: layout/history JSON 파싱 → run_turn
    → events_json + final_layout_json 직렬화

api-server 신규:
  - entities/assets_editorial_article_chat_{sessions,messages}.rs
  - domains/admin/editorial_article_chat.rs (4 handlers)
  - services/decoded_ai_grpc/client.rs::run_chat_turn (deadline 120s)
  - send_message 오케스트레이션: user msg INSERT → load article+history
    → gRPC RunChatTurn → events 순서대로 INSERT → layout UPDATE if changed
    → session.last_message_at touch

web:
  - 2 chat route 가 AI_SERVER_HTTP_URL → API_BASE_URL + Bearer 로 교체
  - server-env.ts 에서 AI_SERVER_HTTP_URL export 삭제

Streaming 은 out of scope (이번 PR 은 unary, send 클릭 후 ~30s 대기. 후속
streaming 은 #448 의 "대화형 강화"). prod ai.decoded.style 외부 노출 차단은
별도 SRE 작업 (이 PR 변경 후 web 이 더 이상 호출하지 않음).

Local 검증:
  - cargo build OK
  - tsc --noEmit OK (chat 파일 clean)
  - gRPC RunChatTurn E2E: layout 'Test 매거진' → 'K-pop 가을 룩' 변경 확인,
    events_json sequence (assistant tool_call → tool result → assistant text)
    + layout_changed=True + final_layout 갱신.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cocoyoon cocoyoon added the bump:patch Bug fixes / internal refactor label May 6, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented May 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
decoded-app Ready Ready Preview, Comment May 6, 2026 4:48am

@cocoyoon cocoyoon merged commit 781cef2 into dev May 6, 2026
7 checks passed
@cocoyoon cocoyoon deleted the fix/editorial-chat-grpc-internal branch May 6, 2026 05:02
@github-project-automation github-project-automation Bot moved this from Todo to Done in decoded-monorepo May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bump:patch Bug fixes / internal refactor

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant