바닐라 JavaScript(프레임워크 없음)를 사용하여 단일 파일 HTML 챗봇을 구축합니다. 전체 파일만 출력합니다. 레이아웃 - 모바일 우선: 휴대폰에서는 전체 화면, 데스크탑에서는 420px 중앙 카드입니다. - 모델 이름을 표시하는 파란색 헤더, 왼쪽의 흰색 봇 버블, 오른쪽의 파란색 사용자 버블, 보내기 버튼이 있는 고정 입력 막대. - 키보드가 레이아웃을 깨뜨리지 않도록 안전 영역 삽입을 존중하고 100dvh를 사용하십시오. CONFIG - 스크립트 상단의 상수: API_URL, API_KEY, MODEL, MAX_TURNS = 12, SYSTEM_MSG, WELCOME. - Xiaomi Mimo 토큰 계획을 사용한 예: const API_URL = 'https://token-plan-sgp.xiaomimimo.com/v1/chat/completions'; const API_KEY = 'API_Key_Placeholder'; // Mimo 모델 const MODEL = 'mimo-v2.6-pro'; const MAX_TURNS = 12; const SYSTEM_MSG = { role: '시스템', content: '당신은 도움이 되는 조수입니다.' }; API - fetch 및 stream: true를 사용하여 OpenAI 호환 /v1/chat/completions 엔드포인트를 호출합니다. - SSE 스트림(데이터: {...} 라인 및 [DONE])을 구문 분석하고 중간 라인을 분할하는 청크를 처리합니다. 렌더링 - 스트리밍하는 동안 깜박이는 커서와 함께 일반 텍스트를 표시합니다. - 응답이 완료되면 markdown을 표시됨.js로 렌더링하고 DOMPurify로 정리합니다(둘 다 CDN에서 로드). - 코드 블록과 테이블은 버블 내부에서 수평으로 스크롤되어야 하며 화면을 넘치지 않아야 합니다. 행동 - 대화 메모리를 유지하고 마지막 MAX_TURNS 턴과 시스템 메시지까지 줄였습니다. - /delete를 입력하면 채팅과 메모리가 지워집니다. - 응답이 스트리밍되는 동안 입력을 비활성화합니다. Enter로 보내세요. - 요청이 실패하면 버블에 우호적인 오류를 표시하고 깨진 차례를 저장하지 마세요. - 부분 SSE 청크, 스트림 중간 오류, 빈 응답, 기록 정리 등 극단적인 사례를 생각해 보세요.