feat(conversation): OpenAI gpt-realtime-2.1 라이브 음성 대화 Premium 백엔드

- realtime-token Edge Function: 티어 검증 + realtime_session 쿼터 + ephemeral key 발급
- useRealtimeConversation 훅: WebRTC 직결 (마이크 → OpenAI, 오디오 자동 재생)
- VoiceConversationPage: conversationBackend 분기 + 연결 실패 시 로컬 fallback
- AppConfig.conversationBackend + SettingsModal 음성 대화 엔진 선택
- ErrorCode 799 ConversationRealtimeTokenFailed, i18n ko/en
This commit is contained in:
Yun Chan 2026-07-21 12:10:13 +09:00
parent 983c60cda2
commit 8f7d300b89
15 changed files with 762 additions and 40 deletions

View file

@ -722,6 +722,37 @@ export function SettingsModal({ open, onClose }: SettingsModalProps): React.Reac
: t('settings.backend.localHint')}
</Typography>
<Divider sx={{ borderColor: d3roPalette.border.subtle }} />
<Typography variant="overline" sx={{ color: d3roPalette.text.label, letterSpacing: '1.5px' }}>
{t('settings.conversationBackend')}
</Typography>
<FormControl size="small">
<InputLabel>{t('settings.conversationBackend')}</InputLabel>
<Select
label={t('settings.conversationBackend')}
value={config.conversationBackend ?? 'local'}
onChange={(e) => {
const next = e.target.value
updateConfig('conversationBackend', next)
if (next === 'realtime') {
// Realtime은 로그인+구독 필요 — 라이선스 모달로 현재 티어 안내
window.dispatchEvent(new Event('d3ro:open-license-modal'))
}
}}
>
<MenuItem value="local">{t('settings.convBackend.local')}</MenuItem>
<MenuItem value="realtime">{t('settings.convBackend.realtime')}</MenuItem>
</Select>
</FormControl>
<Typography variant="body2" sx={{ color: d3roPalette.text.inactive, fontSize: '11px' }}>
{config.conversationBackend === 'realtime'
? t('settings.convBackend.realtimeHint')
: t('settings.convBackend.localHint')}
</Typography>
{config.llmBackend !== 'premium' && (
<>
<Divider sx={{ borderColor: d3roPalette.border.subtle }} />