1.0.1 변경 이력 1.0.0 기준

변경 이력

RAWP-CRS 1.0.1

1.0.0 대비 변경 사항을 정리한 문서입니다.

수정됨

Document Overview

추가된 줄 6 삭제된 줄 6
1 1 # RAWP-CRS 1.0: Client Rendering Specification — Part 1 (§1–§3)
2 2
3 3 > **본 파일은 RAWP-CRS 1.0의 §1–§3을 포함합니다. §4–§6 및 부록은 Part 2를 참조하십시오.**
4 4
5 | 항목 | 값 |
6 | ---------------- | ---------------- |
7 | 상태 | Stable |
8 | 버전 | 1.0 |
9 | 상위 규격 | **RAWP 1.0** |
10 | 데이터 평면 규격 | **RAWP-DPS 1.0** |
5 | 항목 | 값 |
6 | ---------------- | ------------------ |
7 | 상태 | Stable |
8 | 버전 | 1.0.1 |
9 | 상위 규격 | **RAWP 1.0.2** |
10 | 데이터 평면 규격 | **RAWP-DPS 1.0.1** |
11 11
12 12 ---
수정됨

3. 유저 메시지 (User Message)

추가된 줄 34 삭제된 줄 8
1 1 ## 3. 유저 메시지 (User Message)
2 2
3 3 유저 메시지의 설계 목표는 **사용자가 1:1 채팅을 하고 있다는 자연스러운 경험**을 제공하는 것이다. 시각적 형태는 친숙한 메신저 앱의 발신 메시지 관례를 따른다.
4 4
5 5 ### 3.1. 버블 스타일 및 레이아웃
6 6
7 7 **우측 정렬 채팅 버블**: 유저 메시지는 대화 영역의 우측에 배경색이 있는 둥근 모서리(border-radius) 버블로 렌더링해야 한다 (MUST). 버블의 최대 너비는 대화 영역 전체 폭의 70~80%로 제한하여 좌측에 여백을 확보하고, 에이전트 메시지와의 시각적 대칭을 유지한다 (SHOULD).
8 8
9 **텍스트 메시지**: `control.prompt.request`에서 `input_type: "text"`인 메시지는 입력된 원문 텍스트를 버블 내에 그대로 표시한다. 기본적인 마크다운 포맷(볼드, 이텔릭 등)이 포함되어 있더라도, 유저 메시지 버블 내에서는 렌더링하지 않고 원문을 유지하는 것을 기본으로 한다 (SHOULD). 이는 사용자가 자신이 입력한 내용을 정확히 확인할 수 있도록 하기 위함이다.
9 **텍스트 메시지**: `control.prompt.request`에서 `input_type: "text"`인 메시지는 입력된 텍스트를 버블 내에 마크다운 서식을 적용하여 표시한다.
10 10
11 **유저 메시지 서식 인식**: 유저 메시지 버블 내에서 다음의 텍스트 마크다운 서식을 인식하고 렌더링해야 한다 (MUST):
12
13 | 서식 | 구문 | 렌더링 |
14 | --------------- | -------------------------------- | ------------------------------------ |
15 | **볼드** | `**text**` 또는 `__text__` | `font-weight: bold` 적용 |
16 | **이텔릭** | `*text*` 또는 `_text_` | `font-style: italic` 적용 |
17 | **볼드+이텔릭** | `***text***` | 볼드와 이텔릭 동시 적용 |
18 | **취소선** | `~~text~~` | `text-decoration: line-through` 적용 |
19 | **인라인 코드** | `` `code` `` | 모노스페이스 폰트, 배경색 구분 |
20 | **줄바꿈** | Enter 키 (`\n`) 또는 Shift+Enter | `<br>` 줄바꿈 표시 |
21 | **링크** | `[text](url)` | 클릭 가능한 하이퍼링크 |
22 | **자동 링크** | URL 패턴 자동 감지 | 클릭 가능한 링크로 변환 |
23
24 다음 서식은 유저 메시지에서 렌더링하지 않는다 (MUST NOT): 헤더(`#`), 펜스 코드 블록(` ``` `), 테이블(`| |`), 이미지(`![]()`), 목록(`-`, `1.`), 인용구(`>`), 수평선(`---`), 수식(`$`). 유저 메시지는 대화형 텍스트이므로 블록 레벨 구조는 적용하지 않고, 인라인 텍스트 서식만 인식한다.
25
26 **입력창에서의 서식 입력**: 입력창은 사용자가 마크다운 구문을 직접 타이핑하는 플레인 텍스트 모드를 기본으로 한다 (MUST). 서식이 적용된 리치 텍스트 미리보기는 입력 중에 표시하지 않는다 (MUST NOT). 마크다운 구문은 전송 후 대화 이력에 표시될 때 렌더링된다.
27
11 28 **파일 참조 토큰 렌더링**: 전송 완료된 메시지가 대화 이력에 표시될 때, `prompt_text` 내 파일 참조 토큰이 포함되어 있는 경우 §3.4.5의 토큰 시각 사양(배경색, 둥근 모서리, 아이콘)과 동일한 스타일로 인라인 렌더링해야 한다 (MUST). 대화 이력 내 토큰은 읽기 전용이며, 클릭 시 해당 파일의 경로를 클립보드에 복사하거나 파일 뷰어를 여는 동작을 지원할 수 있다 (MAY).
12 29
13 30 **토큰 검증 규칙**: 대화 이력에서 유저 메시지를 렌더링할 때, `prompt_text` 내 토큰 패턴이 `file_references`에 유효하게 매핑되는 경우에만 시각적 토큰으로 렌더링한다 (MUST). 매핑되지 않는 토큰 패턴은 RAWP-DPS §16.2.2에 따라 언이스케이프 후 리터럴 텍스트로 표시하여, 위조된 토큰이 시각적으로 정당한 파일 참조처럼 보이는 것을 방지한다 (MUST).
14 31
15 32 §3.3(슬래시 명령어 실행 버블)의 "중첩 컨테이너 금지" 원칙을 동일하게 따른다. 토큰의 배경색이 버블 배경색과 충분히 구분되어야 하며 (MUST), 버블 내에 별도의 컨테이너(카드, 박스 등)를 추가하지 않는다.
16 33
17 34 ### 3.2. 슬래시 명령어 입력 (Slash Command Input)
18 35
19 36 사용자가 입력창에 `/` 문자를 타이핑하면, 클라이언트는 `agent.commands.publish`(RAWP-DPS §12.1.1)를 통해 수신한 명령어 목록을 기반으로 자동 완성 UI를 즉시 표시해야 한다 (MUST).
20 37
21 38 **트리거 조건**: 입력창에서 커서가 행 시작 위치이거나 공백 직후에 `/` 문자가 입력되면, 자동 완성 팝업을 활성화해야 한다 (MUST). 문장 중간의 슬래시(예: `https://...`, `path/to/file`)에서는 활성화해서는 안 된다 (MUST NOT).
22 39
23 40 **팝업 위치 및 반응 속도**: 자동 완성 팝업은 입력창 바로 위(또는 아래, 뷰포트 공간에 따라 동적 결정)에 오버레이로 표시해야 한다 (MUST). 기존 대화 이력이나 응답 영역을 가려서는 안 되며 (SHOULD NOT), 입력 커서와의 시각적 연결성을 유지해야 한다. `/` 입력 후 팝업 표시까지의 지연은 100ms를 초과해서는 안 된다 (SHOULD NOT). `agent.commands.publish`로 수신한 명령어 목록은 세션 시작 시 로컬에 캐싱하여 네트워크 지연 없이 즉시 표시할 수 있어야 한다 (MUST).
24 41
25 42 **목록 구성**: 각 명령어 항목은 다음 요소를 포함하여 표시해야 한다 (MUST):
26 43
27 44 - **명령어 이름**: `/{name}` 형식으로 좌측에 고정 표시. 모노스페이스 폰트 적용 (SHOULD).
28 45 - **설명(description)**: 명령어 이름 우측 또는 하단에 간략한 설명 텍스트를 표시.
29 46 - **카테고리 표지**: `category` 필드가 존재하면, 색상 뱃지 또는 아이콘으로 시각적 그룹핑을 제공할 수 있다 (MAY). 예: `session` 카테고리는 🔄, `display`는 👁, `config`는 ⚙ 등.
30 47
31 48 **항목 간 시각적 분리 (Item Separation)**: 명령어 목록의 각 항목은 인접 항목과 명확히 구분되어야 한다 (MUST). 다음 방법 중 하나 이상을 적용한다:
32 49
33 50 - **충분한 내부 패딩**: 각 항목에 상하 패딩(예: 8~12px)을 부여하여 텍스트가 경계에 밀착되지 않도록 한다 (MUST). 항목 간 여백 없이 패딩만으로 구분이 충분하면 구분선은 생략할 수 있다.
34 51 - **구분선 또는 배경 교차**: 항목 사이에 얇은 구분선(1px, 저대비 색상)을 삽입하거나, 짝수/홀수 항목에 미세하게 다른 배경색(zebra striping)을 적용할 수 있다 (MAY).
35 52 - **명령어명-설명 레이아웃**: 명령어 이름과 설명 텍스트는 시각적 위계가 명확해야 한다 (MUST). 명령어명은 볼드 또는 기본 텍스트 색상, 설명은 연한 색상(muted color)과 작은 폰트 크기로 차등을 둔다.
36 53
37 54 **실시간 필터링**: 사용자가 `/` 이후 추가 문자를 타이핑하면(예: `/com`), 입력된 접두사와 일치하는 명령어만 팝업에 필터링하여 표시해야 한다 (MUST). 필터링은 명령어 이름(`name`)에 대한 접두사 매칭을 기본으로 하되, 퍼지 매칭(fuzzy match)을 추가 지원할 수 있다 (MAY). 필터링 결과가 갱신될 때, 포커스는 목록의 첫 번째 항목으로 리셋되어야 한다 (SHOULD). 입력된 접두사에 매칭되는 명령어가 없으면, 팝업에 "일치하는 명령어가 없습니다" 등의 안내 메시지를 표시해야 한다 (SHOULD). 팝업을 즉시 닫아서는 안 된다 (MUST NOT) — 사용자가 타이핑을 수정할 기회를 보장해야 한다.
38 55
39 56 **정렬 순서**: 명령어 목록은 다음 우선순위로 정렬할 것을 권장한다 (SHOULD): 사용 빈도 높은 순 → `category`별 그룹핑 → 알파벳순.
40 57
41 58 **포커스 하이라이트 (Focus Highlight)**: 키보드 또는 마우스로 현재 선택 대상이 되는 항목은, 다른 항목과 즉각적으로 구별되는 하이라이트를 적용해야 한다 (MUST). 하이라이트는 해당 항목의 **전체 행 영역**(좌측 끝~우측 끝)에 배경색을 적용하는 방식이어야 하며, 텍스트 일부만 강조하거나 밑줄만 추가하는 방식은 불충분하다. 하이라이트 배경색은 비선택 항목의 배경과 충분한 명도 차이를 가져야 한다 (MUST). 동시에 두 개 이상의 항목이 하이라이트되어서는 안 된다 (MUST NOT). 키보드 포커스와 마우스 호버가 서로 다른 항목을 가리킬 경우, 마우스 호버가 우선한다 (SHOULD).
42 59
43 60 **키보드 내비게이션**: 팝업이 활성화된 상태에서 다음 키보드 조작을 지원해야 한다 (MUST):
44 61
45 62 | 키 | 동작 |
46 63 | ------------------ | ------------------------------------------------------------- |
47 64 | `↑` / `↓` | 목록 항목 간 포커스 이동. 목록 끝에서 순환 (SHOULD). |
48 65 | `Enter` 또는 `Tab` | 포커스된 항목 선택 및 입력창에 반영 |
49 66 | `Esc` | 팝업 닫기, 입력 텍스트는 유지 |
50 67 | 계속 타이핑 | 실시간 필터링 갱신. 포커스는 필터링된 목록의 첫 항목으로 리셋 |
51 68
52 69 팝업 내 목록이 스크롤 가능한 길이일 때, 키보드 포커스가 현재 보이는 영역 밖으로 이동하면 포커스된 항목이 뷰포트 내에 보이도록 팝업 내부를 자동 스크롤해야 한다 (MUST). 마우스 클릭 또는 터치 탭으로도 선택할 수 있어야 하며 (MUST), 마우스 호버 시 해당 항목에 포커스 하이라이트와 동일한 배경색을 즉시 적용해야 한다 (MUST).
53 70
54 71 **선택 후 동작**: 명령어가 선택되면, 입력창의 텍스트를 `/{선택된_name}` (후행 공백 포함)으로 교체하고 팝업을 닫아야 한다 (MUST). `parameters` 배열에 `required: true`인 항목이 있으면, 선택 후 입력창에 해당 파라미터의 힌트를 회색 플레이스홀더로 표시하여 사용자가 추가 입력이 필요함을 인지하도록 해야 한다 (SHOULD).
55 72
56 73 **명령어 목록 갱신**: `agent.commands.publish` 이벤트가 세션 중 재수신되면, 클라이언트는 로컬 캐시를 즉시 갱신해야 한다 (MUST). 팝업이 열려 있는 상태에서 갱신이 발생하면, 현재 필터 조건을 유지한 채 목록을 교체해야 한다 (SHOULD). 갱신 과정에서 사용자의 포커스 위치나 입력 상태가 초기화되어서는 안 된다 (MUST NOT).
57 74
58 75 ### 3.3. 슬래시 명령어 실행 버블 렌더링 (Command Bubble)
59 76
60 77 사용자가 슬래시 명령어를 실행하면, 대화 이력에 표시되는 채팅 버블은 일반 텍스트 메시지와 명확히 구별되는 전용 렌더링을 적용해야 한다 (MUST).
61 78
62 79 **슬래시 접두사 제거**: 채팅 버블에 명령어를 표시할 때 선행 `/` 문자는 제거해야 한다 (MUST). 예: 사용자가 `/compact focus on auth module`을 입력했다면, 버블에는 `compact focus on auth module`로 표시한다.
63 80
64 81 **중첩 컨테이너 금지 (No Nested Containers)**: 명령어 버블은 **버블 자체가 뱃지(badge) 역할**을 겸해야 하며, 버블 내부에 별도의 뱃지, 칩(chip), 또는 박스 요소를 중첩해서는 안 된다 (MUST NOT).
65 82
66 83 **명령어명 강조**: 버블 내에서 명령어명(첫 번째 토큰)은 중첩 컨테이너 없이 **인라인 텍스트 스타일**로 구분해야 한다 (MUST). 명령어명은 **볼드(font-weight: bold)** 와 일반 텍스트 대비 약간 다른 색상을 적용하여 시각적으로 구분한다. 파라미터가 존재하면 일반 두께의 텍스트로 이어서 표시한다. 예: **compact** focus on auth module.
67 84
68 85 **버블 스타일 차별화**: 명령어 버블은 그 자체로 일반 메시지와 즉시 구분되어야 한다 (MUST). 다음 조합을 적용한다:
69 86
70 87 - **인라인 크기**: 내용 길이에 맞춰 최소 폭으로 렌더링 (SHOULD). 일반 메시지처럼 넓은 영역을 차지하지 않고, 컴팩트한 인라인 요소로 표시한다.
71 88 - **배경색 차별화**: 일반 메시지 버블과 명확히 다른 배경색을 적용한다.
72 89 - **모노스페이스 폰트**: 버블 전체에 모노스페이스 폰트를 적용 (SHOULD).
73 90 - **아이콘 접두**: 명령어명 좌측에 소형 아이콘(예: `⚡`, `▶`)을 표시할 수 있다 (MAY).
74 91
75 92 **실행 결과 연결**: 명령어 버블 직후에 에이전트의 응답이 이어지는 경우, 명령어 버블과 결과 영역 사이의 시각적 연결성을 표현하여 인과 관계를 명확히 해야 한다 (SHOULD).
76 93
77 94 **프로토콜 연계**: `control.prompt.request`에서 `input_type: "slash_command"`(RAWP-DPS §6.1.1)로 설정된 프레임은 본 섹션의 Command Bubble 스타일을 적용해야 한다 (MUST). `input_type: "text"` 또는 기타 값인 경우에는 §3.1의 일반 메시지 버블 스타일을 유지한다.
78 95
79 96 ### 3.4. 파일 참조 입력 (File Reference Input)
80 97
81 98 사용자가 `@` 문자를 입력하여 로컬 파일을 인라인으로 참조하는 기능의 렌더링 및 UX 규격이다. 슬래시 명령어(§3.2)와 유사한 자동 완성 팝업 UI 패턴을 따르되, 파일 퍼지 검색의 특성에 맞게 확장한다.
82 99
83 100 #### 3.4.1. 트리거 조건
84 101
85 102 **활성화 조건**: 입력창에서 커서가 행 시작 위치이거나 공백 직후에 `@` 문자가 입력되면, 파일 검색 팝업을 활성화해야 한다 (MUST).
86 103
87 104 **비활성 조건**: 다음의 경우에는 팝업을 활성화해서는 안 된다 (MUST NOT):
88 105
89 106 - `@` 직전 문자가 영숫자(`a-z`, `A-Z`, `0-9`)이거나 `.`인 경우. 이는 이메일 주소 패턴(`user@domain`), URL 내 `@`, 또는 단어 중간의 `@`를 필터링한다.
90 107 - 슬래시 명령어 팝업(§3.2)이 이미 활성 상태인 경우. §3.4.7 참조.
91 108
92 109 #### 3.4.2. 팝업 UI 구성
93 110
94 111 **위치 및 반응 속도**: §3.2(슬래시 명령어)의 팝업 위치 규칙과 동일하게 입력창 바로 위에 오버레이로 표시한다 (MUST). 기존 대화 이력이나 응답 영역을 가려서는 안 되며 (SHOULD NOT), 입력 커서와의 시각적 연결성을 유지해야 한다. `@` 입력 후 팝업 표시까지의 지연은 100ms를 초과해서는 안 된다 (SHOULD NOT).
95 112
96 113 **초기 상태**: `@` 입력 직후(쿼리 문자열이 비어 있는 시점), 팝업은 다음 중 하나를 표시해야 한다 (MUST):
97 114
98 115 - 최근 수정된 파일 목록 (클라이언트가 DPS `control.file.search`의 빈 쿼리 응답으로 제공)
99 116 - "파일명을 입력하세요" 안내 메시지 + 로딩 인디케이터
100 117
101 118 **후보 항목 구성**: 각 파일 후보 항목은 다음 요소를 포함하여 표시해야 한다 (MUST):
102 119
103 120 - **파일 아이콘 (MAY)**: 확장자별 아이콘 또는 이모지를 좌측에 표시한다. 아이콘 매핑 예시:
104 121
105 122 | 확장자 그룹 | 아이콘/이모지 예시 |
106 123 | ---------------------------- | --------------------- |
107 124 | `.ts`, `.tsx`, `.js`, `.jsx` | 📜 또는 JS/TS 아이콘 |
108 125 | `.py` | 🐍 또는 Python 아이콘 |
109 126 | `.json`, `.yaml`, `.toml` | ⚙ 또는 설정 아이콘 |
110 127 | `.md`, `.txt` | 📄 |
111 128 | `.css`, `.scss` | 🎨 |
112 129 | 기타 / 알 수 없음 | 📁 (기본 파일 아이콘) |
113 130
114 131 아이콘 매핑은 클라이언트 구현에 위임하며, 본 규격은 강제하지 않는다 (MAY). 단, 아이콘을 제공하는 경우 모든 후보에 일관되게 적용해야 한다 (MUST).
115 132
116 133 - **파일명**: 볼드 또는 기본 텍스트 색상으로 좌측에 표시. DPS `session.file.candidates`의 `match_ranges`가 제공된 경우, 매칭된 문자 범위를 강조 배경색 또는 볼드로 하이라이팅해야 한다 (MUST).
117 134 - **디렉토리 경로**: 파일명 우측 또는 하단에 연한 색상(muted color)으로 표시. 긴 경로는 선행 부분을 말줄임(`…/deep/path/to/`)으로 축약할 수 있다 (MAY).
118 135
119 136 **항목 간 시각적 분리**: §3.2의 항목 간 시각적 분리 규칙과 동일하게, 충분한 내부 패딩(8~12px)과 선택적 구분선을 적용한다 (MUST).
120 137
121 138 #### 3.4.3. 퍼지 검색 동작
122 139
123 140 **실시간 검색 요청**: 사용자가 `@` 이후 추가 문자를 타이핑하면, 클라이언트는 DPS `control.file.search` 이벤트 발송을 위해 입력을 마스터에 전달해야 한다 (MUST). 키스트로크마다 즉시 전송하지 않고, 150~300ms 디바운싱을 적용하여 네트워크 부하를 제어해야 한다 (SHOULD).
124 141
125 142 **로딩 상태**: 검색 요청 발송 후 `session.file.candidates` 수신 전까지, 팝업 하단에 로딩 인디케이터(스피너 또는 프로그레스 바)를 표시해야 한다 (MUST). 이전 결과가 존재하면 이전 결과를 유지한 채 로딩 인디케이터를 병행 표시하여, 화면이 빈 상태로 깜빡이는 것을 방지한다 (SHOULD).
126 143
127 144 **결과 순서 보장**: 클라이언트는 `session.file.candidates`의 `query_id`를 확인하여, 현재 활성 쿼리의 결과만 팝업에 반영해야 한다 (MUST). `query_id`가 현재 활성 쿼리와 불일치하는 응답(이전 쿼리의 지연 도착)은 무시한다 (MUST).
128 145
129 146 **빈 결과 처리**: 매칭 결과가 없으면 "일치하는 파일이 없습니다" 안내 메시지를 표시해야 한다 (SHOULD). 팝업을 즉시 닫아서는 안 된다 (MUST NOT) — 사용자가 타이핑을 수정할 기회를 보장해야 한다.
130 147
131 148 #### 3.4.4. 키보드 및 포인터 내비게이션
132 149
133 150 §3.2의 키보드 내비게이션 규칙을 동일하게 적용한다 (MUST):
134 151
135 152 | 키 | 동작 |
136 153 | ------------------ | --------------------------------------------------------- |
137 154 | `↑` / `↓` | 목록 항목 간 포커스 이동. 목록 끝에서 순환 (SHOULD). |
138 155 | `Enter` 또는 `Tab` | 포커스된 항목 선택 및 입력창에 반영 |
139 156 | `Esc` | 팝업 닫기, `@` 포함 입력 텍스트는 유지 |
140 157 | 계속 타이핑 | 퍼지 검색 갱신. 포커스는 목록의 첫 항목으로 리셋 (SHOULD) |
141 158
142 159 포커스 하이라이트, 자동 스크롤, 마우스/터치 조작 규칙도 §3.2와 동일하다.
143 160
144 161 **추가 규칙**: `/`(슬래시) 키 입력은 디렉토리 구분자로서 검색 쿼리에 포함되어야 하며, 슬래시 명령어 팝업을 트리거해서는 안 된다 (MUST NOT). 즉, `@` 팝업이 활성 상태인 동안 `/` 입력은 파일 경로 검색의 일부로 처리한다.
145 162
146 163 #### 3.4.5. 선택 후 동작: 파일 참조 토큰 렌더링
147 164
148 165 사용자가 파일을 선택하면, 입력창에서 `@{타이핑한_텍스트}`를 **인라인 파일 참조 토큰**으로 교체해야 한다 (MUST). 이 토큰은 입력창 내에서 일반 텍스트와 시각적으로 명확히 구분되는 독립적 시각 요소로 렌더링한다.
149 166
150 167 **토큰 시각 사양:**
151 168
152 169 - **배경색**: 본문 입력 영역의 배경과 구분되는 연한 강조색(예: 연한 파란색 `#E3F2FD`, 또는 테마의 `primary` 색상의 10~15% 불투명도)을 적용한다 (MUST).
153 170 - **둥근 모서리**: `border-radius: 3~4px`를 적용하여 토큰의 경계를 시각적으로 명확히 한다 (MUST).
154 171 - **내부 패딩**: 좌우 4~6px, 상하 1~2px의 미세한 패딩을 부여한다 (SHOULD).
155 172 - **텍스트 내용**: 파일명만 표시하거나, 짧은 경우 상대 경로 전체를 표시한다. 경로가 긴 경우 `…/` 접두로 축약할 수 있다 (MAY).
156 173 - **파일 아이콘 (MAY)**: 토큰 좌측에 확장자별 소형 아이콘 또는 이모지를 표시한다. §3.4.2의 아이콘 매핑을 따른다. 아이콘은 텍스트와 동일한 줄높이 내에서 수직 중앙 정렬한다.
157 174 - **폰트**: 모노스페이스 폰트를 적용하여 파일 경로임을 시각적으로 암시한다 (SHOULD). 폰트 크기는 입력창의 본문 텍스트와 동일하게 유지한다.
158 175
159 176 **토큰 동작:**
160 177
161 178 - 토큰은 커서 이동 시 **원자 단위(atomic unit)** 로 취급한다 (MUST). 좌/우 화살표로 커서가 토큰에 도달하면 토큰 전체를 건너뛴다. 토큰 내부에 커서가 진입하지 않는다.
162 - `Backspace` 키로 토큰 직후에서 삭제하면, 첫 번째 `Backspace`로 토큰 전체를 선택(하이라이트) 상태로 전환하고, 두 번째 `Backspace`로 토큰을 삭제해야 한다 (SHOULD). 이는 슬랙의 멘션 삭제 UX와 동일하다. 또는 단일 `Backspace`로 즉시 삭제하되, `Ctrl+Z`(undo)로 복원할 수 있게 하는 방식도 허용한다 (MAY).
163 179 - 토큰을 포함한 텍스트의 복사/붙여넣기 시, 토큰은 `@파일명` 형태의 플레인 텍스트로 변환된다 (SHOULD).
164 180
181 **토큰 삭제 (Fluid Deletion):**
182
183 토큰 삭제는 커서 위치에 관계없이 물 흐르듯 자연스러운 시각적 연속성을 유지해야 한다 (MUST). 삭제 과정에서 대화 흐름이 끊기거나 레이아웃이 점프해서는 안 된다 (MUST NOT).
184
185 - **Backspace (토큰 직후에서)**: 첫 번째 `Backspace`로 토큰 전체를 선택(하이라이트) 상태로 전환한다 (MUST). 하이라이트된 토큰은 배경색 변경(예: 기존 연한 파란색 → 연한 빨간색 `#FFEBEE` 또는 테마의 `danger` 색상 10~15% 불투명도)으로 삭제 예정 상태임을 표시한다. 두 번째 `Backspace`로 토큰을 삭제한다.
186 - **Delete (토큰 직전에서)**: `Backspace`와 동일한 2단계 동작을 `Delete` 키에도 적용해야 한다 (MUST).
187 - **삭제 애니메이션**: 토큰이 삭제될 때 너비를 0으로 축소하는 트랜지션(100~150ms)을 적용하여 후속 텍스트가 부드럽게 당겨지도록 해야 한다 (MUST). 즉시 제거하여 텍스트가 갑자기 이동하는 것은 허용하지 않는다 (MUST NOT).
188 - **범위 선택 삭제**: 사용자가 마우스 드래그 또는 Shift+화살표로 토큰을 포함하는 텍스트 범위를 선택한 후 삭제하면, 선택 범위 내의 토큰은 2단계 확인 없이 즉시 삭제한다 (MUST). 이 경우에도 삭제 애니메이션은 적용한다 (SHOULD).
189 - **Undo 지원**: 토큰 삭제 후 `Ctrl+Z`(macOS: `Cmd+Z`)로 토큰을 복원할 수 있어야 한다 (MUST). 복원 시 토큰의 메타데이터(`ref_id`, 파일 경로 등)도 함께 복원된다.
190
165 191 **복수 참조**: 단일 메시지 내에 여러 개의 파일 참조 토큰이 존재할 수 있다 (MUST 지원). 각 토큰은 독립된 `ref_id`를 가지며, 동일 파일을 중복 참조하더라도 별개의 토큰으로 취급한다.
166 192
167 193 #### 3.4.6. 메시지 전송 시 변환 및 이스케이프
168 194
169 195 사용자가 메시지를 전송하면, 클라이언트는 입력창의 콘텐츠를 다음 두 영역으로 분리하여 처리해야 한다 (MUST):
170 196
171 197 - **토큰 영역**: UI 파일 선택을 통해 삽입된 인라인 토큰. DPS §16.2.1의 토큰 포맷(`<@file:ref_id|display_path>`)으로 변환한다. 이스케이프를 적용하지 않는다.
172 198 - **텍스트 영역**: 사용자가 키보드로 직접 입력한 모든 나머지 텍스트. DPS §16.2.2의 이스케이프 규칙을 적용하여 `\` → `\\`, `<@` → `\<@` 변환을 수행한다.
173 199
174 200 이 분리는 입력창의 내부 데이터 모델에서 토큰 노드와 텍스트 노드를 구분하여 관리함으로써 구현한다. 입력창이 단순 텍스트 필드(`<input>`, `<textarea>`)인 경우에도, 토큰 삽입 시점에 내부적으로 토큰 위치와 메타데이터를 별도 추적해야 한다 (MUST).
175 201
176 202 각 토큰에 대응하는 `file_references` 배열을 구성하여 DPS `control.prompt.request`의 `payload`에 포함한다 (MUST).
177 203
178 204 #### 3.4.7. 슬래시 명령어와의 상호 배타
179 205
180 206 `@` 팝업이 활성 상태인 동안 `/` 입력은 파일 경로의 일부로 처리하며, 슬래시 명령어 팝업을 트리거하지 않는다 (MUST). 역으로, `/` 팝업이 활성 상태인 동안 `@` 입력은 명령어 인자의 일부로 처리한다 (SHOULD). 동시에 두 팝업이 활성화되어서는 안 된다 (MUST NOT).
181 207
182 208 ---
183 209
184 210 > **Part 1 끝. §4 에이전트 메시지, §5 시스템 메시지, §6 비스트리밍 환경 적응 및 부록은 Part 2를 참조하십시오.**
185 211
186 212 # RAWP-CRS 1.0: Client Rendering Specification — Part 2 (§4–§6, 부록)
187 213
188 214 > **본 파일은 RAWP-CRS 1.0의 §4–§6 및 부록을 포함합니다. §1–§3(파일 참조 입력 §3.4 포함)은 Part 1을 참조하십시오.**
189 215
190 | 항목 | 값 |
191 | ---------------- | ---------------- |
192 | 상태 | Stable |
193 | 버전 | 1.0 |
194 | 상위 규격 | **RAWP 1.0** |
195 | 데이터 평면 규격 | **RAWP-DPS 1.0** |
216 | 항목 | 값 |
217 | ---------------- | ------------------ |
218 | 상태 | Stable |
219 | 버전 | 1.0.1 |
220 | 상위 규격 | **RAWP 1.0.2** |
221 | 데이터 평면 규격 | **RAWP-DPS 1.0.1** |
196 222
197 223 ---
수정됨

4. 에이전트 메시지 (Agent Message)

추가된 줄 87 삭제된 줄 1
1 1 ## 4. 에이전트 메시지 (Agent Message)
2 2
3 3 에이전트 메시지의 설계 목표는 **다양한 형식의 콘텐츠를 복잡함 없이 제시**하는 것이다. 에이전트는 텍스트, 마크다운, 사고 과정, 도구 호출 결과, 코드 diff, 태스크 목록 등 이질적인 형식의 출력을 생성하며, 이들이 하나의 대화 흐름에서 자연스럽게 읽히도록 해야 한다.
4 4
5 5 ### 4.1. 레이아웃 원칙: 버블리스 디자인 (Bubble-less Design)
6 6
7 7 에이전트 메시지는 채팅 버블로 감싸지 않는다 (MUST NOT). 에이전트 출력에 채팅 버블을 적용하면 다음의 문제가 발생한다:
8 8
9 9 - 코드 블록, diff 뷰어, 태스크 목록 등이 버블 내부에 중첩되어 이중 컨테이너(container-in-container) 구조가 되며, 시각적 노이즈가 증가한다.
10 10 - 버블의 고정 패딩과 최대 너비 제한이 코드, 테이블, diff 등 가로 공간이 필요한 콘텐츠의 가독성을 저해한다.
11 11 - 다양한 콘텐츠 유형(텍스트, 코드, diff, 파일 트리 등)이 동일한 버블 외형으로 감싸져 유형별 시각적 구분이 무너진다.
12 12
13 13 에이전트 출력은 대화 영역의 좌측에 정렬하되, 버블 없이 콘텐츠 자체의 시각적 형태(텍스트 블록, 코드 블록, diff 뷰어, 카드 등)로 유형을 구분한다. 각 콘텐츠 블록 사이에는 충분한 수직 간격(예: 12~16px)을 확보하여 블록 간 경계를 명확히 한다 (SHOULD).
14 14
15 15 ### 4.2. 마크다운 렌더링 (Markdown Rendering)
16 16
17 17 에이전트의 텍스트 응답은 마크다운 형식을 포함할 수 있으며, 클라이언트는 아래에 명시된 마크다운 컴포넌트를 렌더링할 수 있어야 한다. 각 컴포넌트는 지원 수준에 따라 **필수(MUST)**, **권장(SHOULD)**, **선택(MAY)** 으로 분류된다. 필수 컴포넌트를 렌더링하지 못하는 클라이언트는 본 프로토콜의 UI 적합성을 만족하지 못하는 것으로 간주한다.
18 18
19 19 **A. 인라인 텍스트 서식 (Inline Text Formatting)**
20 20
21 21 인라인 서식은 문장 내에서 특정 텍스트 범위에 스타일을 적용하는 요소다. 모든 인라인 서식은 상호 중첩(nesting)이 가능해야 한다 (MUST). 예: `***bold and italic***`, ``**bold with `code`**``.
22 22
23 23 | 컴포넌트 | 마크다운 구문 | 렌더링 명세 | 지원 수준 |
24 24 | ----------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- |
25 25 | **볼드 (Bold)** | `**text**` 또는 `__text__` | `font-weight: bold` 적용. 본문 텍스트보다 시각적으로 두꺼워야 한다. | MUST |
26 26 | **이텔릭 (Italic)** | `*text*` 또는 `_text_` | `font-style: italic` 적용. 기울어진 글꼴로 렌더링한다. | MUST |
27 27 | **볼드+이텔릭** | `***text***` | 볼드와 이텔릭을 동시에 적용. | MUST |
28 28 | **취소선 (Strikethrough)** | `~~text~~` | `text-decoration: line-through` 적용. 텍스트 중앙을 가로지르는 선을 표시한다. | MUST |
29 29 | **인라인 코드 (Inline Code)** | `` `code` `` | 모노스페이스 폰트 적용. 본문 텍스트와 구분되는 배경색(예: 연한 회색)과 미세한 패딩을 부여하여 시각적으로 분리한다. 내부 텍스트는 마크다운 파싱 대상에서 제외(escape)해야 한다. | MUST |
30 30 | **하이라이트 (Highlight)** | `==text==` | `<mark>` 또는 동등한 형광펜 배경색을 적용하여 강조한다. | SHOULD |
31 31 | **밑줄 (Underline)** | `<u>text</u>` (HTML 태그) | `text-decoration: underline` 적용. 링크와의 시각적 혼동을 방지하기 위해 밑줄 색상은 링크 색상과 구분되어야 한다 (SHOULD). | SHOULD |
32 32 | **위첨자 (Superscript)** | `^text^` 또는 `<sup>text</sup>` | 본문 기준선보다 위에, 작은 폰트 크기로 렌더링한다. | SHOULD |
33 33 | **아래첨자 (Subscript)** | `~text~` 또는 `<sub>text</sub>` | 본문 기준선보다 아래에, 작은 폰트 크기로 렌더링한다. 취소선(`~~`)과의 구문 충돌에 주의: 물결표 1개는 아래첨자, 2개는 취소선으로 파싱한다. | SHOULD |
34 34 | **키보드 키 (Keyboard)** | `<kbd>Ctrl</kbd>` | 키캡 스타일의 인라인 요소로 렌더링. 둥근 보더, 미세한 그림자, 모노스페이스 폰트를 적용하여 물리 키보드 키를 시각적으로 모방한다. | MAY |
35 35
36 36 **B. 블록 요소: 헤더 (Headings)**
37 37
38 38 | 컴포넌트 | 마크다운 구문 | 렌더링 명세 | 지원 수준 |
39 39 | ------------ | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
40 40 | **헤더 1~6** | `# H1` ~ `###### H6` | 수준별 폰트 크기와 두께를 차등 적용하여 계층 구조를 시각적으로 표현한다. `H1`이 가장 크고, `H6`이 가장 작다. 모든 헤더는 본문 텍스트보다 크거나 같은 크기에 볼드를 적용해야 한다. | MUST |
41 41
42 42 **헤더 크기 조정**: 에이전트 응답 내 헤더는 독립 문서가 아닌 대화 컨텍스트 안에서 표시되므로, 문서 수준의 과도하게 큰 `H1`은 대화 흐름을 시각적으로 단절시킨다. 클라이언트는 대화 인터페이스에 적합한 크기 범위로 헤더 스케일을 조정해야 한다 (SHOULD). 예: `H1`을 본문 대비 1.4~1.6배, `H2`를 1.2~1.4배 수준으로 제한하고, `H4`~`H6`은 본문과 동일 크기에 볼드 또는 색상 차등만으로 구분할 수 있다.
43 43
44 44 **헤더 간격**: 헤더 상단에는 본문 행간보다 넓은 여백(예: 1.5~2배)을 부여하여 섹션 경계를 명확히 해야 한다 (SHOULD). 헤더 하단 여백은 본문 행간과 동일하거나 약간 넓은 수준으로 유지하여 헤더와 후속 본문의 연결감을 보존한다.
45 45
46 46 **B. 블록 요소: 목록 (Lists)**
47 47
48 48 | 컴포넌트 | 마크다운 구문 | 렌더링 명세 | 지원 수준 |
49 49 | --------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
50 50 | **비순서 목록** | `- item`, `* item`, `+ item` | 불릿 기호(●, ○, ■ 등)와 함께 들여쓰기를 적용하여 렌더링한다. | MUST |
51 51 | **순서 목록** | `1. item`, `2. item` | 숫자 번호와 함께 들여쓰기를 적용하여 렌더링한다. 번호는 마크다운 원문의 숫자가 아닌, 실제 순서를 기반으로 자동 생성해야 한다. | MUST |
52 52 | **중첩 목록** | 들여쓰기(2~4칸)로 하위 항목 | 들여쓰기 수준에 따라 불릿 기호를 차등 적용(예: 1단계 ●, 2단계 ○, 3단계 ■)하고, 각 수준의 들여쓰기가 시각적으로 명확해야 한다. 비순서↔순서 혼합 중첩도 지원해야 한다. | MUST |
53 53 | **체크리스트** | `- [ ] todo`, `- [x] done` | 미체크(☐)와 체크(☑) 상태를 시각적으로 구분하는 체크박스 아이콘을 표시한다. 체크박스는 읽기 전용으로, 사용자가 클릭하여 상태를 변경할 수 없다. | SHOULD |
54 54
55 55 **B. 블록 요소: 코드 (Code Blocks)**
56 56
57 57 | 컴포넌트 | 마크다운 구문 | 렌더링 명세 | 지원 수준 |
58 58 | ----------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
59 59 | **펜스 코드 블록** | ` ```language ... ``` ` | 모노스페이스 폰트, 본문과 구분되는 배경색 컨테이너에 렌더링한다. 내용이 가로로 넘칠 경우 **가로 스크롤**을 지원해야 한다 (MUST). | MUST |
60 60 | **구문 하이라이팅** | ` ```python ` 등 언어 식별자 | 해당 언어의 키워드, 문자열, 주석, 숫자 등을 색상으로 구분하는 구문 하이라이팅을 적용한다. 최소한 주요 언어(Python, JavaScript/TypeScript, Java, C/C++, Go, Rust, HTML, CSS, SQL, Bash, JSON, YAML, Markdown)를 지원해야 한다. | SHOULD |
61 61 | **코드 블록 메타 정보** | — | 코드 블록 상단에 언어명 레이블을 표시하고, 우측 상단에 **복사 버튼**을 제공한다. | SHOULD |
62 62 | **라인 번호** | — | 긴 코드 블록(예: 10줄 이상)에는 좌측에 라인 번호를 표시한다. | MAY |
63 63
64 64 **B. 블록 요소: 테이블 (Tables)**
65 65
66 66 | 컴포넌트 | 마크다운 구문 | 렌더링 명세 | 지원 수준 |
67 67 | ---------- | ------------------ | ------------------------------------------ | --------- |
68 68 | **테이블** | `\| col \| col \|` | 행과 열이 구분된 테이블 형태로 렌더링한다. | MUST |
69 69
70 70 **테이블 상세 명세**: 헤더 행 구분(MUST), 열 정렬(MUST), 행 구분(SHOULD), 셀 패딩(MUST), 오버플로우 시 가로 스크롤(MUST), 셀 내 마크다운(MUST).
71 71
72 72 **B. 블록 요소: 인용, 구분선, 이미지 (Quotes, Dividers, Images)**
73 73
74 74 | 컴포넌트 | 마크다운 구문 | 렌더링 명세 | 지원 수준 |
75 75 | --------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------- | --------- |
76 76 | **인용구** | `> text` | 좌측에 수직 보더(3~4px, 강조 색상 또는 회색)를 배치하고, 본문 대비 들여쓰기를 적용한다. 다중 수준 인용 지원. | MUST |
77 77 | **수평선** | `---`, `***`, `___` | 전체 가용 너비에 걸친 시각적 구분선을 렌더링한다. | MUST |
78 78 | **이미지** | `![alt](url)` | 인라인 이미지로 렌더링. 최대 너비 제한(MUST), 원본 비율 유지(MUST), 로딩 중 placeholder(SHOULD), alt 텍스트 폴백(MUST). | MUST |
79 79 | **이미지 캡션** | `![alt](url "title")` | `title` 속성이 제공된 경우, 이미지 하단에 캡션 텍스트로 표시한다. | MAY |
80 80
81 81 **B. 블록 요소: 링크, 참조 (Links & References)**
82 82
83 83 | 컴포넌트 | 마크다운 구문 | 렌더링 명세 | 지원 수준 |
84 84 | --------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------- | --------- |
85 85 | **인라인 링크** | `[text](url)` | 클릭 가능한 하이퍼링크. 외부 링크는 새 탭/창에서 열어야 한다 (SHOULD). | MUST |
86 86 | **자동 링크** | `<https://...>` 또는 URL 자동 감지 | URL 형태의 텍스트를 자동으로 클릭 가능한 링크로 변환한다. | SHOULD |
87 87 | **참조 링크** | `[text][id]` + `[id]: url` | 참조 스타일 링크를 인라인 링크와 동일하게 렌더링한다. | SHOULD |
88 88 | **각주** | `[^1]` + `[^1]: text` | 본문 내 각주 참조를 위첨자 번호로 표시하고, 클릭 시 대응하는 각주 내용으로 스크롤하거나 툴팁으로 표시한다. | MAY |
89 89
90 90 **C. 수식 (Math / LaTeX)**
91 91
92 92 | 컴포넌트 | 마크다운 구문 | 렌더링 명세 | 지원 수준 |
93 93 | --------------- | ------------- | ------------------------------------------------------------------ | --------- |
94 94 | **인라인 수식** | `$E = mc^2$` | 본문 텍스트 흐름 내에서 수식을 렌더링한다. KaTeX, MathJax 등 사용. | SHOULD |
95 95 | **블록 수식** | `$$\n...\n$$` | 독립된 블록으로 중앙 정렬하여 수식을 렌더링한다. | SHOULD |
96 96
97 97 **D. 다이어그램 (Diagrams)**
98 98
99 99 | 컴포넌트 | 마크다운 구문 | 렌더링 명세 | 지원 수준 |
100 100 | ---------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------- | --------- |
101 101 | **Mermaid 다이어그램** | ` ```mermaid ... ``` ` | Mermaid.js를 사용하여 다이어그램을 SVG 또는 Canvas로 렌더링한다. 렌더링 실패 시 원본 텍스트를 코드 블록으로 폴백 표시한다. | MAY |
102 102
103 103 **E. 기타 요소 (Miscellaneous)**
104 104
105 105 | 컴포넌트 | 마크다운 구문 | 렌더링 명세 | 지원 수준 |
106 106 | -------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
107 107 | **이모지** | `:emoji_name:` | GitHub 스타일 이모지 숏코드를 유니코드 이모지로 변환한다. 유니코드 이모지 직접 입력도 올바르게 렌더링해야 한다 (MUST). | SHOULD |
108 108 | **줄바꿈** | 행 끝 공백 2칸 또는 `<br>` | 명시적 줄바꿈을 적용한다. | MUST |
109 109 | **이스케이프 문자** | `\*`, `\#`, `\_` 등 | 백슬래시로 이스케이프된 마크다운 특수 문자는 리터럴 문자 그대로 표시한다. | MUST |
110 110 | **HTML 인라인 태그** | `<br>`, `<u>`, `<sup>`, `<sub>`, `<mark>`, `<kbd>` | 안전한(safe) HTML 태그에 한해 인라인 렌더링을 허용한다. `<script>`, `<iframe>`, `<style>`, `<form>` 등 보안 위험이 있는 태그는 반드시 무시하거나 이스케이프 처리해야 한다 (MUST). | SHOULD |
111 111
112 112 **스트리밍 중 미완성 마크다운 방어**: 렌더러는 스트리밍 중 마크다운 태그가 닫히지 않은 상태로 전달되더라도 UI가 깨지지 않도록 방어적으로 처리해야 한다 (MUST). 코드 블록은 열림 태그 수신 시 즉시 컨테이너를 생성하고 최소 높이를 할당한다 (SHOULD). 인라인 서식은 임시로 서식을 적용하되 닫는 마커 수신 시 확정한다. 테이블은 구분 행 수신 시점부터 렌더링을 시작한다 (SHOULD).
113 113
114 114 ### 4.3. 점진적 텍스트 렌더링 (Progressive Text Rendering)
115 115
116 116 실시간 스트리밍 환경(WSS 지원 클라이언트)에서의 텍스트 렌더링 지침이다.
117 117
118 118 **버퍼 병합**: 클라이언트는 `content_index` 단위로 수신되는 텍스트 페이로드를 지연 없이 화면에 점진적으로 렌더링해야 한다 (MUST).
119 119
120 120 **오토 스크롤 제어**: 텍스트 생성 중에는 뷰포트 하단을 자동으로 추적하되, 사용자가 과거 이력을 보기 위해 스크롤을 위로 올린 상태(Scroll Up)에서는 읽기 방해를 막기 위해 오토 스크롤을 일시 중단해야 한다 (SHOULD).
121 121
122 122 **스크롤 안정성 (Scroll Stability)**: 클라이언트는 사용자가 현재 읽고 있는 텍스트가 시각적으로 흔들리지 않도록 스크롤 위치를 능동적으로 제어해야 한다 (MUST). 구체적으로 다음을 준수한다:
123 123
124 124 - **앵커 포인트 고정**: 오토 스크롤이 활성화된 상태에서는, 새로운 텍스트가 삽입될 때 현재 생성 중인 마지막 라인이 뷰포트 하단의 일정 영역(예: 하단 20~30% 지점)에 고정되도록 조정해야 한다 (MUST).
125 125 - **상방 삽입 보상 (Upward Insertion Compensation)**: 현재 읽고 있는 영역 **위쪽**에 콘텐츠가 삽입되거나 높이가 변하는 경우, 삽입된 높이만큼 `scrollTop`을 보상하여 현재 보고 있는 텍스트의 화면상 절대 위치가 변하지 않도록 해야 한다 (MUST).
126 126 - **부드러운 추종**: 오토 스크롤 시 `scrollTo`에 `behavior: 'instant'`를 사용하여 프레임 단위로 즉각 추종해야 한다 (SHOULD). `behavior: 'smooth'`는 빠른 텍스트 생성 속도에 뒤처져 누적 지연을 유발할 수 있으므로 스트리밍 중에는 사용하지 않아야 한다 (SHOULD NOT).
127 127 - **높이 변동 최소화**: 코드 블록, 테이블, 이미지 등 높이가 확정되지 않은 요소는 예상 높이를 미리 확보(placeholder/skeleton)하여 렌더링 완료 시 높이 변동폭을 최소화해야 한다 (SHOULD).
128 128
129 129 **텍스트 출현의 시각적 연속성 (Visual Continuity of Text Appearance)**: 점진적으로 생성되는 텍스트는 사용자에게 **매끄럽고 연속적인 흐름**으로 인지되어야 한다 (MUST). 구체적으로 다음을 준수한다:
130 130
131 131 - **마이크로 배칭 및 보간**: 클라이언트는 수신된 `agent.text.delta` 토큰을 짧은 시간 윈도우(예: 30~60ms) 내에 모아 한 번에 렌더링하거나, `requestAnimationFrame` 주기에 동기화하여 프레임당 일정량의 텍스트를 출력하는 방식을 적용해야 한다 (SHOULD). 단, 배칭으로 인한 체감 지연이 100ms를 초과해서는 안 된다 (MUST NOT).
132 132 - **출현 애니메이션**: 새로 삽입되는 텍스트에 미세한 페이드인 또는 수직 슬라이드인 효과를 적용할 수 있다 (MAY). 적용 시 애니메이션 지속 시간은 50~120ms 이내로 제한해야 한다 (MUST). 애니메이션은 **가장 최근에 추가된 텍스트 청크에만** 적용하며, 이미 표시된 텍스트가 반복적으로 애니메이션되어서는 안 된다 (MUST NOT).
133 133 - **하단 경계 효과 제한**: 생성 중인 텍스트의 하단 경계에 블러, 그라데이션 페이드 등의 시각 효과를 적용하는 경우, 효과 영역의 높이는 **텍스트 2줄 이내**(약 40~48px)로 제한한다 (MUST). 블러 강도는 **4px 이하**로 제한한다 (SHOULD). 맥동, 깜빡임, 색상 순환 등 동적 변화를 하단 경계 효과에 적용해서는 안 된다 (MUST NOT). 생성 완료(`agent.text.done`) 시 즉시 제거하거나 100ms 이내에 페이드아웃해야 한다 (MUST).
134 134 - **읽기 흐름 보호 원칙**: 점진적 렌더링의 모든 시각적 처리는 다음의 상위 원칙을 따라야 한다: **사용자가 이미 생성된 텍스트를 읽는 행위를 방해해서는 안 된다 (MUST NOT).**
135 135
136 136 ### 4.4. 사고 과정 시각화 (Thinking Process)
137 137
138 138 **시각적 분리**: `agent.thinking.delta`의 내용은 일반 응답 텍스트와 명확히 구분되는 별도의 컨테이너(예: 인용구, 배경색이 다른 블록)에 렌더링해야 한다 (MUST).
139 139
140 140 **진행 상태 표현 (Thinking Indicator)**: 사고 과정이 진행 중일 때, 사용자에게 에이전트가 능동적으로 작업 중임을 시각적으로 전달해야 한다 (MUST). 그라데이션 애니메이션(SHOULD), 1.5~3초 사이의 느린 호흡 리듬(SHOULD), "Thinking…" 레이블(MUST)을 포함한다.
141 141
142 142 **실시간 텍스트 노출 정책**: 사고 스트림의 텍스트 본문을 사용자에게 실시간으로 노출할지 여부는 클라이언트 설정에 따른다. 요약 모드(기본값 권장)와 실시간 모드를 지원할 것을 권장한다 (SHOULD).
143 143
144 144 **상태 전이 및 제거**: `agent.thinking.done` 수신 시, 그라데이션 애니메이션을 즉시 중단하고 (MUST), 접힌 상태로 전환하여 "Thought for Ns" 요약 한 줄만 표시한다 (SHOULD). 활성 → 접힘 전환은 150~300ms 트랜지션으로 처리한다 (SHOULD). 후속 `agent.text.delta` 영역으로 시선을 유도한다 (SHOULD).
145 145
146 146 **마스킹 처리**: `redacted: true`인 경우 `[사고 내용 생략]` 등의 플레이스홀더로 마스킹하고 (MUST), 펼침 동작 자체를 비활성화한다 (MUST).
147 147
148 148 **다중 사고 블록**: 각 `content_index`별로 독립된 사고 컨테이너를 생성하되, 동시에 두 개 이상의 Thinking Indicator가 활성 상태로 표시되어서는 안 된다 (MUST NOT).
149 149
150 ### 4.5. 도구 호출 결과 렌더링 (Tool Result Rendering)
150 ### 4.5. 도구 가용 상태 및 호출 결과 렌더링 (Tool Status & Result Rendering)
151 151
152 #### 4.5.1. 도구 가용 상태 표시 (Tool Availability Indicator)
153
154 `tool.catalog.publish`(RAWP-DPS 1.0.1 §5.4.1) 수신 시, 각 도구의 `status` 필드에 따라 가용 상태를 시각적으로 구분하여 표시해야 한다 (MUST). 도구 목록을 노출하는 모든 UI(도구 팔레트, 사이드바, 도구 호출 헤더 등)에 적용한다.
155
156 **상태별 시각 표현:**
157
158 | `status` | 시각 표현 | 도구명 스타일 | 상호작용 |
159 | ------------- | ----------------------------------------------- | ---------------------------------------------- | ------------------ |
160 | `available` | 없음 (기본 상태이므로 별도 표시 불필요) | 기본 텍스트 | 정상 사용 가능 |
161 | `unavailable` | 도구명 좌측에 금지 아이콘(🚫) 또는 빨간 점 표시 | 흐린 텍스트(opacity 50%), 취소선 적용 (SHOULD) | 클릭/선택 비활성화 |
162 | `degraded` | 도구명 좌측에 경고 아이콘(⚠) 또는 주황 점 표시 | 기본 텍스트 유지 | 정상 사용 가능 |
163
164 **상태 사유 표시**: 도구의 `status_description` 필드(RAWP-DPS 1.0.1 §5.4.1)가 존재하면, 도구명 하단에 한 줄로 사유를 표시해야 한다 (MUST). `unavailable`이면 연한 빨간 텍스트, `degraded`이면 연한 주황 텍스트로 표시한다. `status_description`이 없으면 사유를 표시하지 않는다 (MUST NOT). 예: `Bash` 아래에 `실행 파일을 찾을 수 없음`.
165
166 **진단 메시지 연동**: `diagnostics` 배열에 해당 도구의 진단(`tool_name` 일치)이 포함된 경우, 도구 항목에 호버 또는 탭 시 진단 메시지를 툴팁으로 표시할 수 있다 (MAY).
167
168 **도구 카탈로그 갱신**: `tool.catalog.publish`가 세션 중 재수신되면, 도구 목록과 상태를 즉시 갱신해야 한다 (MUST). 이전에 `unavailable`이었던 도구가 `available`로 전이되면 금지 표시를 즉시 제거한다.
169
170 #### 4.5.2. 도구 호출 결과 렌더링 (Tool Result Rendering)
171
152 172 **진행 중 표시**: `tool.invoke.request` 수신 시, 도구명과 함께 스피너를 인라인으로 표시해야 한다 (MUST). `tool.invoke.stream` 수신 시에는 실시간 출력을 점진적으로 렌더링해야 한다 (SHOULD).
153 173
154 174 **병렬 도구 그룹화**: 동일한 `parallel_group_id`를 가진 복수의 `tool.invoke.request`는 하나의 그룹 컨테이너로 묶어 표시해야 한다 (SHOULD).
155 175
156 176 **완료 전환**: `tool.invoke.result` 수신 시, 스피너를 즉시 중단하고 `output_type`에 적합한 결과 뷰어로 전환해야 한다 (MUST). 뷰어 매핑:
157 177
158 178 | `output_type` | 권장 뷰어 | 비고 |
159 179 | -------------- | ----------------------------- | --------------------------------- |
160 180 | `text` | 모노스페이스 텍스트 블록 | Bash stdout 등 |
161 181 | `diff` | 구문 인지 Diff 뷰어 | §4.6 참조 (MUST) |
162 182 | `file_content` | 라인 번호 포함 코드 뷰어 | 구문 하이라이팅 적용 (SHOULD) |
163 183 | `file_list` | 파일 트리 또는 경로 목록 | 클릭 시 해당 파일 열기 지원 (MAY) |
164 184 | `web_content` | 링크 포함 요약 카드 | 출처 URL 표시 (MUST) |
165 185 | `structured` | JSON 트리 뷰어 또는 전용 위젯 | TodoRead 등은 §4.8 참조 |
166 186 | `empty` | 성공 체크마크 한 줄 | "✅ Write completed" 등 |
167 187 | `agent_result` | 서브에이전트 결과 접이식 블록 | 클릭 시 전체 결과 펼침 (SHOULD) |
168 188
189 **파일 조작 결과 헤더**: `tool.invoke.result`에서 도구가 파일 조작 도구(`category: "filesystem"`, `tool_name` ∈ {Write, Edit, MultiEdit} 또는 동등 도구)인 경우, 결과 헤더에 파일 조작 유형을 명시적으로 표시해야 한다 (MUST):
190
191 | 조작 유형 | 헤더 표시 예시 | 시각적 힌트 |
192 | --------- | ----------------------- | -------------- |
193 | 파일 생성 | `Created: {file_path}` | 녹색 계열 강조 |
194 | 파일 수정 | `Modified: {file_path}` | 기본 색상 |
195 | 파일 삭제 | `Deleted: {file_path}` | 빨간 계열 강조 |
196
197 조작 유형의 판단은 도구의 `tool_name`과 `input` 필드에서 유추한다. 예: `tool_name: "Write"`이면 파일 생성 또는 덮어쓰기, `tool_name: "Edit"`이면 수정.
198
169 199 **에러 결과 표시**: `status`가 `error`, `timeout`, `cancelled`인 경우, 에러 상태를 시각적으로 구분하여 표시해야 한다 (MUST).
170 200
171 201 **접이식 기본 동작**: 도구 결과는 기본적으로 접힌 상태로 표시하되, 결과 요약 한 줄을 노출하고 클릭 시 전체 결과를 펼칠 수 있어야 한다 (SHOULD). 단, `output_type: diff`인 경우에는 기본 펼침 상태를 허용한다 (MAY).
172 202
173 203 ### 4.6. Code Diff 렌더링 (Diff Viewer)
174 204
175 205 `output_type: diff` 또는 `output_type: text`이면서 내용이 Unified Diff 형식인 도구 결과는, **구문 인지 Diff 뷰어**로 렌더링해야 한다 (MUST).
176 206
177 207 **Diff 형식 자동 감지**: `output_type`이 `text`인 경우에도, 출력 내용의 첫 10라인 이내에 `--- a/`, `+++ b/`, `@@` 등 Unified Diff 시그니처가 감지되면 Diff 뷰어로 자동 전환해야 한다 (SHOULD).
178 208
179 209 **라인 수준 색상 구분**: 삭제=빨강 계열, 추가=녹색 계열의 대비가 즉각적으로 인지되어야 한다 (MUST).
180 210
181 211 | 접두 문자 | 의미 | 라이트 테마 배경 | 다크 테마 배경 |
182 212 | ------------ | -------------- | ---------------- | -------------- |
183 213 | `-` | 삭제된 라인 | `#fdd` | `#3d1114` |
184 214 | `+` | 추가된 라인 | `#dfd` | `#1a361a` |
185 215 | `@@` | 청크 헤더 | `#def` | `#1a2a3a` |
186 216 | (공백) | 컨텍스트 라인 | 투명 | 투명 |
187 217 | `diff --git` | 파일 경계 헤더 | 연한 회색 | 어두운 회색 |
188 218
189 219 **인라인 단어 수준 하이라이팅**: 동일 위치의 삭제/추가 라인 쌍에 대해, 라인 내 실제로 변경된 단어/문자 범위를 추가 강조할 것을 권장한다 (SHOULD).
190 220
191 221 **라인 번호 표시**: 원본(old)과 변경(new)의 라인 번호를 이중 컬럼으로 표시해야 한다 (SHOULD).
192 222
193 223 **파일 헤더 구분**: 여러 파일의 변경 사항이 포함된 경우, 각 파일 경계를 명확한 헤더로 구분해야 한다 (MUST). 파일 단위 접기/펼치기를 지원할 것을 권장한다 (SHOULD).
194 224
195 225 **뷰 모드 전환**: Unified View(기본값)와 Side-by-side View를 제공할 것을 권장한다 (SHOULD).
196 226
197 227 **접근성 고려**: 색상과 함께 접두 기호(`-`, `+`)를 항상 가시적으로 유지하고, 선택적으로 아이콘 또는 패턴을 병행 표시할 것을 권장한다 (SHOULD).
198 228
229 **변경 통계 요약 표시**: Diff 헤더 또는 푸터에 변경 통계를 한 줄로 요약 표시해야 한다 (MUST). 형식: `+{추가_라인_수} -{삭제_라인_수}`. 예: `+12 -3`.
230
231 **파일 생성/삭제 배지**:
232
233 - 모든 라인이 `+`(추가)인 Diff는 파일 전체가 신규 생성되었음을 의미한다. Diff 상단에 `New file` 배지를 표시해야 한다 (MUST).
234 - 모든 라인이 `-`(삭제)인 Diff는 파일 전체가 삭제되었음을 의미한다. Diff 상단에 `File deleted` 배지를 표시해야 한다 (MUST).
235 - 배지는 파일 헤더 영역 내에서 파일명과 함께 표시하며, 해당 색상(생성=녹색, 삭제=빨간) 계열의 배경을 적용한다 (SHOULD).
236
237 **라인 수준 추가/삭제 시각화**: `tool.invoke.result`의 `output`에 라인별 추가/삭제 정보가 포함된 경우(구조화 Diff 또는 Unified Diff), 개별 라인의 추가/삭제를 본 절의 라인 수준 색상 구분 규칙(삭제=빨강, 추가=녹색)에 따라 표시해야 한다 (MUST).
238
199 239 ### 4.7. 에이전트 상태 표시 (Agent State Indicator)
200 240
201 241 `agent.state.changed` 이벤트는 에이전트의 내부 상태 전이를 실시간으로 통보한다. 각각 독립된 채팅 메시지로 렌더링해서는 안 된다 (MUST NOT).
202 242
203 243 **단일 인라인 상태 표시줄**: 클라이언트는 에이전트의 현재 상태를 대화 영역의 고정된 단일 위치에 표시하고, 수신 시마다 **제자리 갱신(in-place update)** 해야 한다 (MUST).
204 244
205 245 **상태별 렌더링**: `thinking` → `🧠 Thinking…` (그라데이션 펄스), `tool_calling` → `🔧 Running tool…` (스피너), `awaiting_input` → `⏸ Waiting for input` (정적), `error` → `⚠ Error occurred` (붉은 강조), `idle` → 표시줄 제거.
206 246
207 247 **전환 애니메이션**: 100~200ms 이내 크로스페이드 또는 슬라이드 (SHOULD). 전환 속도가 상태 변경 빈도보다 느리면 애니메이션을 생략하고 즉시 교체해야 한다 (MUST).
208 248
209 249 **유휴 상태 처리**: `idle` 전이 시 즉시 제거하거나 200~300ms 페이드아웃 (MUST). Turn 완료 후 대화 이력에 흔적이 남아서는 안 된다 (MUST NOT).
210 250
211 251 **대화 이력 비오염 원칙**: `agent.state.changed` 이벤트는 대화 이력에 영구적 항목으로 기록해서는 안 된다 (MUST NOT). 상태 표시는 순수하게 일시적(ephemeral)이다.
212 252
213 253 ### 4.8. 태스크 목록 렌더링 (Task List Rendering)
214 254
215 255 `output_type: structured` 형태의 TodoRead/TodoWrite 결과(RAWP-DPS §8.2)를 수신하면, 클라이언트는 전용 태스크 관리 UI를 실시간으로 갱신해야 한다 (SHOULD).
216 256
217 257 **태스크 상태 시각화**:
218 258
219 259 | `status` | 시각 표현 | 비고 |
220 260 | ------------- | -------------------------------- | -------------------------- |
221 261 | `pending` | ○ 빈 원 또는 미체크 체크박스 | 회색 텍스트 |
222 262 | `in_progress` | ◐ 반원 또는 스피너 부착 체크박스 | 볼드 텍스트, 강조 배경 |
223 263 | `completed` | ● 채워진 원 또는 체크된 체크박스 | 취소선 텍스트 (SHOULD) |
224 264 | `cancelled` | ✕ 취소 표시 | 흐린 텍스트, 불투명도 감소 |
225 265
226 266 **계층 구조 지원**: `parent_id`가 존재하는 태스크는 부모 태스크 하위에 들여쓰기하여 트리 구조로 렌더링해야 한다 (SHOULD).
227 267
228 268 **전환 애니메이션**: 태스크 상태 변경 시 부드러운 전환 애니메이션을 적용해야 한다 (SHOULD). 다수의 태스크가 동시에 갱신되는 경우 개별 애니메이션을 생략하고 전체 목록을 일괄 교체할 수 있다 (MAY).
229 269
270 ### 4.9. Turn 내 콘텐츠 순서 보장 (Content Ordering within Turn)
271
272 에이전트의 단일 Turn은 텍스트 블록, 사고 과정, 도구 호출이 교차(interleave)하여 발생할 수 있다. 이 교차 콘텐츠의 렌더링 순서 규칙을 정의한다.
273
274 **수신 순서 렌더링 원칙**: 모든 콘텐츠 블록은 수신 순서대로 대화 영역에 아래로 추가해야 한다 (MUST). 이미 렌더링된 요소의 순서를 재배치(reorder)해서는 안 된다 (MUST NOT).
275
276 **마지막 텍스트 블록 최하단 보장 (Last Text Anchoring)**: 에이전트가 Turn 내에서 마지막으로 생성하는 텍스트 블록(`agent.text.delta` → `agent.text.done`)은 해당 Turn의 시각적 렌더링에서 항상 최하단에 위치해야 한다 (MUST). 이는 수신 순서 렌더링 원칙에 의해 자연스럽게 보장된다 — 마지막 텍스트 블록은 마지막에 수신되므로 최하단에 추가된다.
277
278 **시퀀스 예시:**
279
280 | 수신 순서 | 이벤트 | 렌더링 위치 |
281 | --------- | ---------------------------------- | ----------------------------- |
282 | 1 | `agent.text.delta` (텍스트 A) | 최상단 |
283 | 2 | `tool.invoke.request` (도구 X) | 텍스트 A 아래 |
284 | 3 | `tool.invoke.result` (도구 X 결과) | 도구 X 요청 아래 |
285 | 4 | `agent.text.delta` (텍스트 B) | 도구 X 결과 아래 **(최하단)** |
286
287 텍스트 B가 에이전트의 마지막 텍스트 블록이므로, Turn 완료 시 최하단에 위치한다. 이후 추가 도구 호출 없이 `session.turn.end`가 수신되면, 텍스트 B가 사용자에게 가장 마지막으로 보이는 콘텐츠가 된다.
288
289 **도구 호출로 Turn이 종료되는 경우**: 에이전트가 텍스트 출력 후 도구 호출을 수행하고 추가 텍스트 없이 Turn이 종료되면, 도구 결과가 최하단이 된다. 이는 허용되는 동작이다.
290
291 ### 4.10. 서브에이전트 메시지 렌더링 (Subagent Message Rendering)
292
293 RAWP-DPS 1.0.1 §10의 서브에이전트 위임 규격에 따라, `metadata.subagent_context`가 포함된 메시지의 렌더링 규칙을 정의한다.
294
295 #### 4.10.1. 메시지 그룹핑
296
297 `subagent_context`가 존재하는 연속 메시지(동일 `parent_invocation_id`)는 시각적으로 그룹핑하여 메인 에이전트의 메시지와 구분해야 한다 (MUST).
298
299 **그룹 헤더**: 그룹 상단에 서브에이전트의 `agent_type`과 `description`을 표시해야 한다 (MUST). `agent_type`이 없으면 `Subagent`와 같은 일반 레이블을 사용한다. 헤더는 서브에이전트임을 즉시 인지할 수 있는 시각적 구분(아이콘, 배경색 차등, 좌측 보더 등)을 포함해야 한다 (MUST).
300
301 **중첩 서브에이전트**: `parent_invocation_id` 체인으로 식별되는 중첩 서브에이전트(서브에이전트 내에서 호출된 서브에이전트)는 들여쓰기 또는 시각적 계층으로 표현해야 한다 (SHOULD).
302
303 **접기/펼치기**: 서브에이전트 그룹은 접기/펼치기가 가능해야 한다 (SHOULD). 진행 중인 서브에이전트는 펼침 상태, `agent.subagent.ended` 수신 후 완료된 서브에이전트는 접힌 상태를 기본으로 한다 (SHOULD). 접힌 상태에서는 그룹 헤더와 결과 요약 한 줄만 표시한다.
304
305 #### 4.10.2. 서브에이전트 도구 호출 표시
306
307 - 서브에이전트 내의 도구 호출은 해당 서브에이전트 그룹 내에서 표시해야 한다 (MUST). 메인 에이전트의 도구 호출과 섞이면 안 된다 (MUST NOT).
308 - 서브에이전트 내의 도구 호출은 §4.5.2와 동일한 UI 컴포넌트를 사용하되, 서브에이전트 그룹 컨텍스트 내에 위치해야 한다.
309 - `subagent` 필드가 포함된 `tool.invoke.request`(서브에이전트를 호출하는 도구 자체)는 일반 도구 호출과 시각적으로 구분해야 한다 (SHOULD). 예: 전용 아이콘, 색상, `Subagent` 배지.
310
311 #### 4.10.3. 서브에이전트 미지원 폴백
312
313 - `subagent_context`가 없거나 `null`인 메시지는 그룹핑 없이 플랫하게 표시해야 한다 (MUST). 이것이 서브에이전트 미지원 에이전트의 기본 동작이다.
314 - `output_type: "agent_result"`인 `tool.invoke.result`는 `subagent_context` 없이도 서브에이전트 결과임을 암시한다. 이 경우 해당 tool request/result 쌍을 "서브에이전트 호출"로 표시할 수 있다 (MAY). 단, 내부 메시지 그룹핑은 불가능하다.
315
230 316 ---
수정됨

5. 시스템 메시지 (System Message)

추가된 줄 69 삭제된 줄 0
1 1 ## 5. 시스템 메시지 (System Message)
2 2
3 3 시스템 메시지의 설계 목표는 대화의 맥락과 상태를 **빠짐없이, 직관적으로** 전달하는 것이다. 시스템 메시지는 프로토콜 또는 클라이언트가 생성한 상태 안내로, 대화의 두 참여자(User, Agent) 사이의 메타 정보를 전달한다.
4 4
5 5 ### 5.1. 레이아웃 원칙: 중앙 정렬, 생략 금지
6 6
7 7 **중앙 정렬**: 시스템 메시지는 대화 영역의 수평 중앙에 정렬해야 한다 (MUST).
8 8
9 9 **내용 생략 절대 금지 (No Ellipsis, No Truncation)**: 시스템 메시지의 텍스트는 어떠한 경우에도 말줄임표나 텍스트 잘림으로 생략되어서는 안 된다 (MUST NOT).
10 10
11 11 **짧고 직관적인 메시지**: 시스템 메시지의 본문은 최대한 짧고 직관적으로 작성해야 한다 (MUST). 예: `⏹ 응답이 중지되었습니다`, `⚠ 세션 연결이 끊어졌습니다`.
12 12
13 13 **긴 내용의 드롭다운 처리**: 시스템 메시지가 한 줄로 표현하기 어려운 상세 정보를 포함하는 경우 다음의 드롭다운 패턴을 적용해야 한다 (MUST):
14 14
15 15 - **요약 행**: 항상 노출되는 한 줄의 핵심 메시지. 예: `⚠ 도구 실행 실패 — 상세 보기 ▾`
16 16 - **상세 영역**: 요약 행 하단에 접힌 상태로 배치. 사용자가 클릭 시 펼쳐져 전체 내용을 표시한다. 펼침 상태에서도 모든 텍스트가 완전히 노출되어야 하며 (MUST), 내부 스크롤이나 추가 생략을 적용해서는 안 된다 (MUST NOT).
17 17 - **펼침/접힘 토글**: 요약 행 우측에 화살표(▾/▴)를 배치하여 상세 영역의 존재를 시각적으로 암시한다 (MUST).
18 18
19 19 **시각적 비중 최소화**: 시스템 메시지는 사용자 메시지나 에이전트 응답보다 시각적 비중이 낮아야 한다 (SHOULD). 작은 폰트 크기, 연한 텍스트 색상, 배경색 없음 등으로 존재감을 줄이되, 완전히 보이지 않을 정도로 숨겨서는 안 된다.
20 20
21 21 **반응형 너비 확보**: 시스템 메시지 컨테이너의 가용 너비는 대화 영역 전체 폭의 **60% 이상**을 확보해야 한다 (MUST). 최대 너비는 **90% 이내**로 제한해야 한다 (SHOULD). 뷰포트 너비가 480px 이하인 환경에서는 좌우 여백을 최소화(예: 좌우 각 8~12px)하여 텍스트 영역을 우선 확보해야 한다 (SHOULD). 드롭다운 상세 영역은 요약 행과 **동일한 컨테이너 너비**를 유지해야 한다 (MUST).
22 22
23 23 ### 5.2. 사용자 중지 피드백 (Cancellation Feedback)
24 24
25 25 사용자가 중지 버튼을 눌러 진행 중인 Turn을 취소하면(`control.prompt.cancel` 발송), 클라이언트는 대화 이력에 시스템 메시지를 삽입하여 취소가 실행되었음을 명시적으로 기록해야 한다 (MUST). 이는 대화 이력에 영구적으로 남는 항목이다.
26 26
27 27 **렌더링 규격**: §5.1의 레이아웃 원칙에 따라 중앙 정렬, 연한 텍스트, 배경색 없음으로 표시한다. 간결한 메시지(예: `⏹ 응답이 중지되었습니다`)를 사용한다.
28 28
29 29 **삽입 위치 및 타이밍**: 에이전트의 마지막 출력 바로 아래에 삽입해야 한다 (MUST). `control.prompt.cancel` 발송 직후 즉시 표시하여 사용자에게 지체 없이 피드백해야 한다 (SHOULD).
30 30
31 31 **부분 응답 보존**: 중지 이전까지 수신된 `agent.text.delta` 텍스트는 삭제하지 않고 그대로 유지해야 한다 (MUST).
32 32
33 33 **에이전트 상태 정리와의 관계**: 시스템 메시지가 삽입되면, §4.7의 에이전트 상태 표시줄은 즉시 제거되어야 한다 (MUST).
34 34
35 35 ### 5.3. 에러 및 경고 메시지
36 36
37 37 에이전트 에러(`agent.error`), 세션 에러(`session.error`), 연결 단절, 토큰 만료 등의 시스템 이벤트는 시스템 메시지로 표시한다.
38 38
39 39 **심각도별 시각 차등**:
40 40
41 41 | 심각도 | 시각 표현 | 예시 |
42 42 | --------- | ---------------------------------------------- | --------------------------------- |
43 43 | `info` | 기본 시스템 메시지 스타일 (연한 텍스트) | `ℹ 세션이 재연결되었습니다` |
44 44 | `warning` | 주황/노랑 계열 아이콘, 텍스트는 기본 색상 유지 | `⚠ 연결이 불안정합니다` |
45 45 | `fatal` | 빨강 계열 아이콘, 텍스트도 강조 색상 적용 | `❌ 세션이 비정상 종료되었습니다` |
46 46
47 47 **에러 상세 정보**: 에러 메시지에 기술적 상세가 포함되는 경우, §5.1의 드롭다운 패턴을 적용하여 요약 행 + 접이식 상세 영역으로 구성한다 (MUST).
48 48
49 ### 5.4. 세션 이벤트 메시지 (Session Event Messages)
50
51 세션 수준의 상태 변경 이벤트(`session.renamed`, `session.deleted`)는 시스템 메시지로 대화 이력에 삽입하여 사용자에게 상태 변화를 명시적으로 전달해야 한다 (MUST). §5.1의 레이아웃 원칙(중앙 정렬, 생략 금지, 시각적 비중 최소화)을 따른다.
52
53 #### 5.4.1. 세션 이름 변경 (`session.renamed`)
54
55 RAWP-DPS 1.0.1 §7.6.1의 `session.renamed` 이벤트 수신 시, 대화 이력에 시스템 메시지를 삽입해야 한다 (MUST).
56
57 **렌더링 규격:**
58
59 - **메시지 형식**: `세션 이름이 "{previous_name}"에서 "{name}"으로 변경되었습니다` 형태로 표시한다. `previous_name`이 없으면 `세션 이름이 "{name}"(으)로 변경되었습니다`로 표시한다.
60 - **심각도**: `info` 수준. §5.3의 `info` 스타일(연한 텍스트)을 적용한다.
61 - **대화 이력 기록**: 영구적 항목으로 대화 이력에 기록한다. 세션 재연결 시에도 표시되어야 한다.
62 - **변경 주체 표시**: `renamed_by` 값에 따라 변경 주체를 괄호 안에 부기할 수 있다 (MAY). 예: `세션 이름이 "작업 A"(으)로 변경되었습니다 (원격)`.
63 - **UI 제목 반영**: 대화 창의 제목 표시줄 또는 세션 목록에 세션 이름이 표시되는 경우, 해당 영역도 즉시 갱신해야 한다 (MUST).
64
65 #### 5.4.2. 세션 종료 (`session.deleted`)
66
67 RAWP-DPS 1.0.1 §7.7.1의 `session.deleted` 이벤트 수신 시, 대화 이력에 시스템 메시지를 삽입하고 세션의 종료 상태를 시각적으로 확정해야 한다 (MUST).
68
69 **렌더링 규격:**
70
71 - **`reason`별 메시지:**
72
73 | `reason` | 시스템 메시지 예시 | 심각도 |
74 | ---------------- | ---------------------------------------- | --------- |
75 | `user_request` | `세션이 종료되었습니다` | `info` |
76 | `master_request` | `세션이 원격에서 종료되었습니다` | `info` |
77 | `timeout` | `연결 시간 초과로 세션이 종료되었습니다` | `warning` |
78 | `error` | `오류로 인해 세션이 종료되었습니다` | `fatal` |
79
80 - **심각도별 스타일**: §5.3의 심각도별 시각 차등 규칙을 적용한다.
81 - **입력 비활성화**: 세션 종료 메시지 표시 후, 입력창을 비활성화하거나 "세션이 종료되었습니다" 플레이스홀더를 표시하여 추가 입력이 불가능함을 명확히 해야 한다 (MUST).
82 - **에이전트 상태 정리**: §4.7의 에이전트 상태 표시줄이 활성 상태이면 즉시 제거해야 한다 (MUST).
83 - **진행 중 항목 시각 전환**: 세션 종료 시점에 진행 중이었던 도구 호출 스피너(§4.5.2)가 존재하면, 스피너를 중단하고 `cancelled` 상태로 전환하여 표시해야 한다 (MUST). 이는 RAWP-DPS 1.0.1 §7.5.3에서 발송되는 `tool.invoke.result` (status: `"cancelled"`) 수신과 연동된다.
84 - **대화 이력 기록**: 영구적 항목으로 대화 이력에 기록한다.
85
86 ### 5.5. 연결 단절 및 복구 피드백 (Disconnect & Recovery Feedback)
87
88 WSS Connection이 비정상 종료되거나 재연결에 성공한 경우의 렌더링 규칙을 정의한다. RAWP-DPS 1.0.1 §7.8의 Finalization/Unfinalization 절차와 연동된다.
89
90 #### 5.5.1. 연결 단절 시 렌더링 (Finalization)
91
92 WSS 단절이 감지되면(RAWP-DPS 1.0.1 §7.8.2) 다음을 수행해야 한다 (MUST):
93
94 **시스템 메시지 삽입**: `⚠ 연결이 끊어졌습니다`를 §5.3의 `warning` 심각도 스타일로 대화 이력에 삽입한다. 영구적 항목으로 기록한다.
95
96 **스트리밍 텍스트 중단**: 활성 스트리밍 중이던 텍스트(`agent.text.delta`)는 수신된 지점까지 확정하고, 하단 경계 효과(§4.3)를 즉시 제거한다 (MUST). 텍스트 끝에 시각적 절단 표시(예: `…` 또는 흐린 경계선)를 추가하여 텍스트가 완전하지 않음을 나타낼 수 있다 (MAY).
97
98 **도구 호출 스피너 전환**: 진행 중이던 도구 호출 스피너를 즉시 중단하고, `cancelled` 상태 표시(§4.5.2의 에러 결과 표시)로 전환해야 한다 (MUST). 합성된 cancelled 결과(RAWP-DPS 1.0.1 §7.8.1의 `synthetic: true`)는 연한 회색 텍스트로 `연결 끊김으로 취소됨` 등의 메시지를 표시한다.
99
100 **사고 과정 중단**: 활성 Thinking Indicator(§4.4)를 즉시 중단하고 접힌 상태로 전환해야 한다 (MUST).
101
102 **에이전트 상태 표시줄 제거**: §4.7의 상태 표시줄을 즉시 제거하고 입력 가능 상태로 복원해야 한다 (MUST).
103
104 **상호작용 요청 폐기**: 활성 상태인 상호작용 UI(승인 버튼, 선택 팝업 등)를 즉시 닫고, 해당 영역에 `연결 끊김으로 취소됨`을 표시해야 한다 (MUST).
105
106 #### 5.5.2. 재연결 시 렌더링 (Unfinalization)
107
108 WSS 재연결이 성공하고 `session.history`(RAWP-DPS 1.0.1 §7.1.1)를 수신하면 다음을 수행해야 한다 (MUST):
109
110 **시스템 메시지 삽입**: `ℹ 연결이 복구되었습니다`를 §5.3의 `info` 심각도 스타일로 대화 이력에 삽입한다.
111
112 **합성 블록 제거**: Finalization에서 삽입한 합성 cancelled 결과(`synthetic: true`)를 제거하고, `session.history`의 실제 프레임으로 대체한다 (MUST).
113
114 **스트리밍 재개**: `session.history` 재생 후 에이전트가 응답을 계속 생성 중이면(새 `agent.text.delta` 수신), 스트리밍 렌더링을 정상 재개한다.
115
116 **복구 불가 시**: `session.history`의 `buffer_status.truncated`가 `true`이면, `⚠ 일부 메시지가 유실되었습니다`를 `warning` 심각도로 추가 표시해야 한다 (MUST). 합성 블록은 제거하지 않고 유지한다.
117
49 118 ---
수정됨

부록: 관련 규격 문서

추가된 줄 2 삭제된 줄 2
1 1 ## 부록: 관련 규격 문서
2 2
3 3 | 문서 | 설명 |
4 4 | ----------------------- | --------------------------------------------------------------------------- |
5 | **RAWP 1.0** | 원격 에이전트 제어 프로토콜 (상위 규격). 본 문서의 상위 문서. |
6 | **RAWP-DPS 1.0** | 데이터 평면 스트리밍 규격. 본 문서가 참조하는 이벤트 타입 및 페이로드 정의. |
5 | **RAWP 1.0.2** | 원격 에이전트 제어 프로토콜 (상위 규격). 본 문서의 상위 문서. |
6 | **RAWP-DPS 1.0.1** | 데이터 평면 스트리밍 규격. 본 문서가 참조하는 이벤트 타입 및 페이로드 정의. |
7 7 | **RAWP-DPS-0.1-Legacy** | 데이터 평면 스트리밍 규격 (단종 예고). 레거시 호환용. |