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